Downloading Files from HTTP(s)
Instead of processing HTTP headers, chunked encoding, and doing socket management, you can mount an HTTP(s) website (that is unaware of the project) as a filesystem and use standard file operations to download files. This approach is much simpler and handles all the HTTP complexity for you.
Use HTTPS for public resources. Plain HTTP is supported primarily for local testing, such as serving files from your development machine.
You must link libspdos in your project to use these filesystem functions. See the File I/O example for CMake setup instructions.
The code below uses mount point 3 for the HTTP(s) mount (preferred for app and business file access), not mount point 1 (often used for loading Spectranext programs from HTTPS).
Overview
By mounting an HTTP(s) URL as a filesystem, you can:
- Use
open(),read(), andclose()instead of HTTP libraries - Avoid parsing headers, handling chunked encoding, or managing sockets
- Work with files as if they were local
- Copy files between filesystems easily
Basic Example
Here's a simple example that mounts an HTTP(s) filesystem and downloads a file:
#include <spdos.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>
int main(void) {
// Mount HTTPS filesystem at mount point 3 (preferred for public app/business data)
if (mount(3, NULL, NULL, "/test/https", "spectranext.net", "https") < 0) {
printf("Failed to mount HTTP(s) filesystem\n");
return 1;
}
// Switch to mount point 3
setmountpoint(3);
// Open file from HTTP(s) (just like a local file!)
int fd = open("folder/file-d.bin", O_RDONLY, 0);
if (fd < 0) {
printf("Failed to open file\n");
umount(3);
return 1;
}
// Read file content
unsigned char buffer[256];
ssize_t bytes_read;
int total_bytes = 0;
while ((bytes_read = read(fd, buffer, sizeof(buffer))) > 0) {
// Process buffer here (e.g., save to another file, display, etc.)
total_bytes += bytes_read;
}
close(fd);
umount(3);
printf("Downloaded %d bytes\n", total_bytes);
return 0;
}
Downloading and Saving to Local Filesystem
This example downloads a file from HTTP(s) and saves it to the local XFS filesystem. The destination file is written to the RAM layer; commit it later if it should survive power loss.
#include <spdos.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>
int main(void) {
// Mount HTTPS filesystem at mount point 3 (preferred for public app/business data)
if (mount(3, NULL, NULL, "/test/https", "spectranext.net", "https") < 0) {
printf("Failed to mount HTTPS\n");
return 1;
}
// Mount local XFS filesystem at mount point 0 (if not already mounted)
mount(0, NULL, NULL, "", "ram", "xfs");
// Switch to HTTP(s) mount point and open source file
setmountpoint(3);
int src_fd = open("folder/file-d.bin", O_RDONLY, 0);
if (src_fd < 0) {
printf("Failed to open source file\n");
umount(3);
return 1;
}
// Switch to local XFS and open destination file
setmountpoint(0);
int dst_fd = open("downloaded.bin", O_WRONLY | O_CREAT | O_TRUNC, 0);
if (dst_fd < 0) {
printf("Failed to create destination file\n");
close(src_fd);
umount(3);
return 1;
}
// Copy data from HTTP(s) to local XFS
unsigned char buffer[256];
ssize_t bytes_read, bytes_written;
int total_bytes = 0;
while ((bytes_read = read(src_fd, buffer, sizeof(buffer))) > 0) {
bytes_written = write(dst_fd, buffer, bytes_read);
if (bytes_written != bytes_read) {
printf("Write error\n");
close(dst_fd);
close(src_fd);
umount(3);
return 1;
}
total_bytes += bytes_read;
}
close(dst_fd);
close(src_fd);
umount(3);
printf("Downloaded and saved %d bytes to downloaded.bin\n", total_bytes);
return 0;
}
Browsing and Downloading Multiple Files
This example lists files in an HTTP(s) directory and downloads all files:
#include <spdos.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>
int main(void) {
// Mount HTTPS filesystem
if (mount(3, NULL, NULL, "/test/https", "spectranext.net", "https") < 0) {
printf("Mount failed\n");
return 1;
}
// Mount local XFS for saving downloads
mount(0, NULL, NULL, "", "ram", "xfs");
setmountpoint(3);
// Open directory
int dir = opendir(".");
if (dir < 0) {
printf("Failed to open directory\n");
umount(3);
return 1;
}
// Read directory entries
char entry[256];
int file_count = 0;
while (readdir(dir, entry) == 0) {
// Skip directories
if (isdir(entry)) {
continue;
}
printf("Downloading: %s\n", entry);
// Open source file from HTTP(s)
setmountpoint(3);
int src_fd = open(entry, O_RDONLY, 0);
if (src_fd < 0) {
printf(" Failed to open\n");
continue;
}
// Open destination file in local XFS
setmountpoint(0);
int dst_fd = open(entry, O_WRONLY | O_CREAT | O_TRUNC, 0);
if (dst_fd < 0) {
printf(" Failed to create destination\n");
close(src_fd);
continue;
}
// Copy file
unsigned char buffer[256];
ssize_t bytes_read, bytes_written;
int total = 0;
while ((bytes_read = read(src_fd, buffer, sizeof(buffer))) > 0) {
bytes_written = write(dst_fd, buffer, bytes_read);
if (bytes_written != bytes_read) {
printf(" Write error\n");
break;
}
total += bytes_read;
}
close(dst_fd);
close(src_fd);
printf(" Downloaded %d bytes\n", total);
file_count++;
}
closedir(dir);
umount(3);
printf("Downloaded %d files\n", file_count);
return 0;
}
Advantages Over HTTP Libraries
Using the HTTP(s) filesystem approach has several advantages:
- No HTTP complexity: No need to parse headers, handle chunked encoding, or manage HTTP state
- Standard file operations: Use familiar
open(),read(),write(),close()functions - Automatic retry: The filesystem layer handles network errors and retries
- Easy file copying: Copy files between filesystems using standard read/write loops
- Directory browsing: Use
opendir()andreaddir()to browse remote directories - File information: Use
stat()to get file sizes before downloading
Comparison: HTTP Library vs HTTP(s) Filesystem
Using HTTP Library (Complex)
#include <http.h>
#include <sys/socket.h>
// Set up URI
URI uri = {
.proto = "https",
.host = "spectranext.net",
.port = 443,
.location = "/test/https/file.bin",
.user = NULL,
.passwd = NULL
};
// Make request
int sockfd = request(GET, &uri);
if (sockfd < 0) {
// Handle error
}
// Read headers
int http_code;
if (readHeaders(sockfd, &http_code) < 0) {
// Handle error
}
// Check status code
if (http_code != 200) {
// Handle error
}
// Read data (handle chunked encoding, timeouts, etc.)
char buffer[256];
while (readData(sockfd, buffer, sizeof(buffer)) > 0) {
// Process data
}
// Clean up
sockclose(sockfd);
freeheaders();
Using HTTP(s) Filesystem (Simple)
#include <spdos.h>
#include <fcntl.h>
// Mount filesystem
mount(3, NULL, NULL, "/test/https", "spectranext.net", "https");
setmountpoint(3);
// Open and read file (that's it!)
int fd = open("file.bin", O_RDONLY, 0);
unsigned char buffer[256];
while (read(fd, buffer, sizeof(buffer)) > 0) {
// Process data
}
close(fd);
umount(3);
Requirements
For directory browsing to work, the HTTP(s) server must provide an index.txt file in each directory. See the HTTP(s) Filesystem documentation for details on the index.txt format.
For simple file downloads, you can directly open files by their path without needing index.txt.
Next Steps
- HTTP(s) Filesystem - Learn more about mounting HTTP(s) filesystems
- libspdos API Reference - Complete reference for filesystem functions
- File I/O Examples - More examples of file operations