# How to Share Files via R2 Presigned URLs with @cloudflare/computer/assets

> Learn to securely share files with R2 presigned URLs using the @cloudflare/computer/assets module. Generate temporary public access links without exposing credentials.

- Repository: [Cloudflare/computer](https://github.com/cloudflare/computer)
- Tags: how-to-guide
- Published: 2026-08-08

---

**The @cloudflare/computer/assets module provides a streamlined API to upload files to Cloudflare R2 and generate time-limited, presigned GET URLs that allow secure, temporary public access without exposing your credentials.**

The cloudflare/computer repository provides a powerful framework for building AI agents that execute code in secure, isolated workspaces. When these agents generate files that need to be shared with end users—such as charts, screenshots, or build artifacts—the **@cloudflare/computer/assets** module offers a secure way to upload those files to Cloudflare R2 and create presigned URLs for temporary access.

## Setting Up the Assets Client

### Prerequisites

Before generating presigned URLs, you need an R2 bucket binding configured in your Worker environment. The assets client requires **S3-compatible credentials** (account ID, access key, and secret key) to authenticate with R2's API, though these are typically read from environment variables rather than hardcoded.

### Initializing the Client

Create an assets client by calling `createAssets()` from [`packages/computer/src/assets/index.ts`](https://github.com/cloudflare/computer/blob/main/packages/computer/src/assets/index.ts) (lines 3-14). The function accepts a configuration object containing your workspace instance, R2 bucket binding, and optional S3 credentials.

```typescript
import { createAssets } from "@cloudflare/computer/assets";

const assets = createAssets({
  ws,                                 // WorkspaceLike (provides fs.stat/readFile and sessionId)
  bucket: env.ASSETS,                // R2 binding from the Worker environment
  s3: { bucket: "agent-assets" },    // R2 bucket name; credentials are read from env by default
});

```

The `ws` parameter must implement the `WorkspaceLike` interface, providing filesystem methods (`fs.stat`, `fs.readFile`) and a `sessionId` for organizing uploads.

## Uploading and Sharing Files

### The share Method

The primary method for generating presigned URLs is `assets.share()`, implemented in [`packages/computer/src/assets/index.ts`](https://github.com/cloudflare/computer/blob/main/packages/computer/src/assets/index.ts) (lines 101-130). This method handles the complete workflow: streaming the file from the workspace's virtual file system, uploading it to R2 via `bucket.put()`, and returning a presigned URL generated using AWS Signature Version 4.

```typescript
const url = await assets.share("/workspace/out/image.png", {
  expiresAfter: 30_000,                 // 30 seconds (maximum 7 days)
  prefix: `/agent-${ws.sessionId}`,     // optional key prefix
  disposition: "attachment",           // force download (optional)
});

```

### Configuration Options

The `share` method accepts an options object that controls the generated URL's behavior:

- **expiresAfter**: The time-to-live in milliseconds, capped at 7 days (604,800 seconds) per R2's maximum limit
- **prefix**: A string prepended to the object key for organizational purposes, such as namespacing by agent session ID
- **disposition**: When set to `"attachment"`, sets the Content-Disposition header to force browser downloads rather than inline display

## How Presigned URLs Work Under the Hood

When you call `share()`, the module streams the file using a `FixedLengthStream` sized according to `fs.stat(path)`. The actual upload occurs via the R2 binding's `put()` method, defined in [`packages/computer/src/assets/upload.js`](https://github.com/cloudflare/computer/blob/main/packages/computer/src/assets/upload.js).

After a successful upload, the presigned URL is generated using the **AWS SigV4 algorithm** implemented in [`packages/computer/src/assets/sigv4.ts`](https://github.com/cloudflare/computer/blob/main/packages/computer/src/assets/sigv4.ts) (lines 101-118). This algorithm creates a signed request that embeds temporary authentication parameters into the URL query string, allowing anyone with the URL to access the object without possessing your actual R2 credentials.

## Consuming the Presigned URL

The returned URL points directly to the R2 object at `/assets/<bucket>/<key>`. Because it includes the presigned authentication parameters, anyone with the URL can download the file via standard HTTP GET requests without additional authentication.

```typescript
// Example consumer (could be a browser, curl, etc.)
const response = await fetch(url);
const blob = await response.blob();
// Save or display the file

```

## Summary

- The assets client in [`packages/computer/src/assets/index.ts`](https://github.com/cloudflare/computer/blob/main/packages/computer/src/assets/index.ts) provides `createAssets()` to bind your workspace to an R2 bucket using S3-compatible credentials
- The `share()` method in the same file uploads files and returns time-limited URLs using AWS SigV4 signing from [`packages/computer/src/assets/sigv4.ts`](https://github.com/cloudflare/computer/blob/main/packages/computer/src/assets/sigv4.ts)
- Configuration supports custom expiration up to 7 days, key prefixes for organization, and content disposition headers for download behavior
- The RPC-exposed `WorkspaceAssetsStub` in [`packages/computer/src/stub.ts`](https://github.com/cloudflare/computer/blob/main/packages/computer/src/stub.ts) and shell command wiring in [`packages/computer/src/backends/worker-shell/assets-command.ts`](https://github.com/cloudflare/computer/blob/main/packages/computer/src/backends/worker-shell/assets-command.ts) enable integration with the broader Computer framework

## Frequently Asked Questions

### What is the maximum expiration time for R2 presigned URLs?

R2 accepts a maximum expiration of 7 days (604,800 seconds) for presigned URLs. While the `expiresAfter` parameter in the `share()` method accepts milliseconds, values exceeding this limit will be constrained by R2's service-side validation.

### How does @cloudflare/computer/assets handle file streaming?

The implementation creates a `FixedLengthStream` sized from `fs.stat(path)` to stream the file content efficiently from the workspace's virtual file system to R2 via `bucket.put()`. This approach avoids loading entire files into memory, making it suitable for large artifacts generated by Computer agents.

### Can I customize the object key prefix when sharing files?

Yes. Pass the `prefix` option when calling `share()` to prepend a custom string to the object key. This is particularly useful when organizing assets by session ID or agent type, as shown in the pattern `prefix: /agent-${ws.sessionId}`.

### Where does the assets client obtain R2 authentication credentials?

While you explicitly configure the bucket name via the `s3.bucket` parameter, the S3-compatible credentials (account ID, access key, secret key) are read from environment variables by default. You can override this behavior by passing a complete credentials object to the S3 configuration in `createAssets()`.