How to Implement File Upload and Download Operations Within OpenSandbox Sandboxes

Developers can implement file upload and download operations within OpenSandbox sandboxes by using the HTTP-based filesystem API exposed by the execd daemon, utilizing the FilesystemAdapter class for multipart uploads via POST /files/upload and ranged downloads via GET /files/download.

The Alibaba OpenSandbox project provides a secure, isolated execution environment where the sandbox's file system is treated as a regular HTTP service. To implement file upload and download operations within OpenSandbox sandboxes, developers interact with the execd daemon running inside each container through dedicated REST endpoints. The Python SDK abstracts these low-level HTTP calls through the FilesystemAdapter class and high-level WriteEntry models, enabling both single-file operations and batch transfers with full metadata control.

Understanding OpenSandbox's File System Architecture

OpenSandbox exposes the sandbox file system through the execd daemon as a stateless HTTP service. This design allows external clients to perform file operations without requiring direct shell access or volume mounts.

The two primary endpoints for file transfer are:

Operation HTTP Method Endpoint Purpose
Upload POST /files/upload Transfers one or more files with JSON metadata (target path, permissions, ownership)
Download GET /files/download Retrieves raw file bytes; supports the HTTP Range header for partial content

According to the OpenSandbox source code, the FilesystemAdapter in opensandbox/adapters/filesystem_adapter.py manages the httpx.AsyncClient connection to these endpoints, handling authentication and request construction internally.

Uploading Files to an OpenSandbox Sandbox

Uploads are handled as multipart/form-data requests where each file is accompanied by a metadata JSON object describing the destination path and file attributes.

Constructing WriteEntry Objects

Before uploading, developers create WriteEntry instances defined in opensandbox/models/filesystem.py. Each entry encapsulates the target path, data payload, and optional Unix permissions.

from opensandbox.models.filesystem import WriteEntry

entry = WriteEntry(
    path="/workspace/hello.txt",
    data=b"hello execd\n",
    mode=0o644,
    owner="sandbox",
    group="sandbox"
)

The data field accepts bytes, str, or binary streams, allowing flexible input sources.

Using FilesystemAdapter for Batch Uploads

The FilesystemAdapter.write_files method (lines 71-84 in opensandbox/adapters/filesystem_adapter.py) constructs the multipart payload and executes the POST request to /files/upload.

from opensandbox import OpenSandbox
from opensandbox.config import ConnectionConfig
from opensandbox.models.filesystem import WriteEntry

# Initialize connection

cfg = ConnectionConfig(
    protocol="http",
    host="localhost",
    port=8080,
    request_timeout=30,
)

sandbox = await OpenSandbox.create(
    connection_config=cfg,
    sandbox_id="my-sandbox"
)

# Upload multiple files in one request

entries = [
    WriteEntry(path="/workspace/config.json", data=b'{"key": "value"}', mode=0o600),
    WriteEntry(path="/workspace/script.py", data=open("local_script.py", "rb"), mode=0o755),
]

await sandbox.files.write_files(entries)

The generated OpenAPI client in api/execd/api/filesystem/upload_file.py (lines 30-44) handles the low-level HTTP serialization of these multipart parts.

Downloading Files from an OpenSandbox Sandbox

Download operations retrieve file contents through the GET /files/download endpoint, with full support for HTTP range requests and streaming.

Full File Downloads

For complete file retrieval, the FilesystemAdapter uses _build_download_request (lines 59-68 in opensandbox/adapters/filesystem_adapter.py) to construct the request, then returns the raw bytes.


# Download entire file as bytes

content = await sandbox.files.read_bytes("/workspace/hello.txt")
print(content.decode("utf-8"))

Partial Downloads with HTTP Range Headers

OpenSandbox supports the standard HTTP Range header for resumable transfers or selective byte extraction. Pass the range specification to read_bytes via the range_header parameter.


# Retrieve bytes 0-4 (first 5 bytes)

partial = await sandbox.files.read_bytes(
    "/workspace/large.bin",
    range_header="bytes=0-4"
)
print(f"First 5 bytes: {partial}")

The generated client in api/execd/api/filesystem/download_file.py (lines 30-48) serializes these range headers into the outgoing HTTP request.

Streaming Large Files

To avoid loading large files into memory, use the streaming interface read_bytes_stream, which yields chunks asynchronously.

async for chunk in sandbox.files.read_bytes_stream(
    "/workspace/big.dat",
    chunk_size=4 * 1024 * 1024  # 4 MiB chunks

):
    process_chunk(chunk)  # Your processing logic here

This method utilizes httpx's streaming capabilities with client.send(..., stream=True) under the hood.

Key Source Files and Implementation Details

The following files in the alibaba/OpenSandbox repository define the file transfer implementation:

File Path Description
sdks/sandbox/python/src/opensandbox/adapters/filesystem_adapter.py Core adapter containing write_files (lines 71-84) and _build_download_request (lines 59-68)
sdks/sandbox/python/src/opensandbox/api/execd/api/filesystem/upload_file.py Generated OpenAPI client for POST /files/upload (lines 30-44)
sdks/sandbox/python/src/opensandbox/api/execd/api/filesystem/download_file.py Generated OpenAPI client for GET /files/download (lines 30-48)
sdks/sandbox/python/src/opensandbox/models/filesystem.py Data models including WriteEntry for upload metadata
sdks/sandbox/python/src/opensandbox/services/filesystem.py Abstract Filesystem service interface exposed as sandbox.files
components/execd/tests/smoke_api.py End-to-end tests demonstrating raw HTTP upload/download

Summary

  • OpenSandbox exposes sandbox file systems via HTTP endpoints served by the execd daemon, eliminating the need for direct container access.
  • Uploads use POST /files/upload with multipart/form-data payloads containing JSON metadata and raw file bytes, implemented in FilesystemAdapter.write_files.
  • Downloads use GET /files/download with support for HTTP Range headers for partial content, implemented in the adapter's download methods.
  • The Python SDK provides high-level abstractions (sandbox.files.write_file, read_bytes, read_bytes_stream) that wrap the low-level HTTP interactions.
  • All file operations support Unix permissions, ownership, and streaming for memory-efficient handling of large files.

Frequently Asked Questions

What HTTP endpoints does OpenSandbox use for file operations?

OpenSandbox uses two primary REST endpoints exposed by the execd daemon: POST /files/upload for sending files to the sandbox and GET /files/download for retrieving them. Both endpoints accept standard HTTP headers, with the download endpoint supporting Range headers for partial content requests.

How do I upload multiple files in a single request?

Use the write_files method of the FilesystemAdapter (accessed via sandbox.files.write_files) and pass a list of WriteEntry objects. Each WriteEntry specifies the target path, data payload, and file permissions. The SDK automatically constructs a multipart/form-data request containing all files and their metadata, sending them to the POST /files/upload endpoint in one HTTP call.

Does OpenSandbox support resumable or partial file downloads?

Yes, the download implementation supports HTTP Range headers, allowing you to request specific byte ranges of a file. When calling sandbox.files.read_bytes, pass the range_header parameter with a value like "bytes=0-1023" to retrieve partial content. This enables resumable downloads and memory-efficient processing of large files without loading them entirely into RAM.

What is the maximum file size supported for uploads?

The OpenSandbox source code does not enforce a specific file size limit within the SDK itself; constraints depend on the execd daemon's configuration and the underlying storage available to the sandbox container. For large files, use streaming uploads by passing file-like objects (binary streams) as the data parameter in WriteEntry rather than loading entire files into memory as bytes.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →