# File Transfer

quicproquo supports encrypted file transfer with chunked upload/download,
SHA-256 content addressing, and automatic MIME type detection. Files up to
50 MB are supported.

## Sending a file

```
/send-file /path/to/document.pdf
```

Or use the short alias:

```
/sf /path/to/document.pdf
```

This will:

1. Read the file and compute its SHA-256 hash
2. Upload the file in **256 KB chunks** via the `uploadBlob` RPC
3. Verify the hash on the server side
4. Send a `FileRef` message to the active conversation containing the
   blob ID (SHA-256 hash), filename, file size, and MIME type

A progress bar is displayed during upload.

## Downloading a file

```
/download 7
```

Or:

```
/dl 7
```

Where `7` is the history index of the FileRef message. This will:

1. Fetch the blob in chunks via the `downloadBlob` RPC
2. Verify the SHA-256 hash matches the FileRef's blob ID
3. Save the file to the current directory using the original filename

If a file with the same name already exists, a suffix is appended
(`-1`, `-2`, etc.) to avoid overwriting.

## How it works

### Content-addressable storage

Files are stored on the server by their SHA-256 hash (`blob_id`). This
means identical files are automatically deduplicated — uploading the same
file twice reuses the existing blob.

### Chunked transfer

Files are split into 256 KB chunks for upload and download. This:

- Keeps memory usage bounded for large files
- Allows progress reporting
- Enables future resumable transfers

### FileRef message type

The `FileRef` (type code `0x08`) is sent as a regular MLS-encrypted message:

```
[blob_id: 32 bytes (SHA-256)]
[filename_len: 2 bytes BE][filename: UTF-8]
[file_size: 8 bytes BE]
[mime_len: 2 bytes BE][mime_type: UTF-8]
```

The server stores a JSON `.meta` sidecar alongside each blob with metadata.

### MIME type detection

MIME types are detected automatically using the `mime_guess` crate based on
file extension. For example:

- `report.pdf` → `application/pdf`
- `photo.jpg` → `image/jpeg`
- `data.csv` → `text/csv`

### Limits

- **Maximum file size:** 50 MB
- **Chunk size:** 256 KB
- **Hash algorithm:** SHA-256

### RPC methods

| Method | Ordinal | Description |
|---|---|---|
| `uploadBlob` | `@21` | Chunked file upload with SHA-256 content addressing |
| `downloadBlob` | `@22` | Chunked file download with hash verification |

### Error codes

| Code | Meaning |
|---|---|
| E024 | Blob upload failed |
| E025 | Blob download failed |
| E026 | Blob hash mismatch |
| E027 | Blob operation error |

## Implementation

- **Server:** `crates/quicproquo-server/src/node_service/blob_ops.rs`
- **Client REPL:** `/send-file` and `/download` in `crates/quicproquo-client/src/client/repl.rs`
- **Message type:** `FileRef` variant in `crates/quicproquo-core/src/app_message.rs`
