# 檔案傳輸與區域網直連

> HTML: https://remote.ivjn.us/docs/zh-TW/files-and-lan/

Agent、Exchange、CLI、網頁控制台和手機控制端支援檔案傳輸。支援的裝置會宣告 `files` 能力。

## 檔案傳輸

```sh
remote-cli file i5m ls /tmp
remote-cli file i5m upload ./example.zip /tmp/example.zip
remote-cli file i5m download /tmp/example.zip ./downloaded.zip
remote-cli file i5m fetch https://example.com/example.zip ./example.zip
```

預設不覆蓋已有檔案；上傳或下載時新增 `--overwrite` 才允許覆蓋。CLI 使用 Ctrl+C 取消，網頁和手機控制端提供取消按鈕。網頁在裝置詳情的“檔案”頁操作，手機控制端從裝置詳情進入“檔案傳輸”。

傳輸分塊為 64 KiB，每塊確認後繼續。單檔案上限 1 GiB；網頁下載上限 128 MiB，較大檔案請使用 CLI 或手機控制端。目錄最多回傳 1000 項，不支援遞迴目錄上傳。上傳在目標目錄寫入臨時檔案，完整接收後原子替換；取消、斷線或逾時會清理未完成的臨時檔案。CLI 下載也使用臨時檔案，手機端下載到快取後呼叫系統分享/儲存。

檔案訪問使用 Agent 程序的系統許可權，不限制在某個共享目錄。唯讀帳號不能列目錄、上傳或下載；Exchange 沿用裝置所屬工作區、會話隔離和操作審計，不記錄檔案內容。Android 上 `.` 指向 Agent 應用檔案目錄，訪問其他目錄受 Android 許可權限制，不能繞過系統沙箱。

## 透過 Agent 下載網路檔案

在網頁檔案頁輸入 HTTP/HTTPS 網址，或執行 `file DEVICE fetch URL LOCAL`。Agent 從自身網路下載並串流傳回 Console 電腦，不在 Agent 儲存檔案。網頁上限 128 MiB，CLI 上限 1 GiB；取消、斷線或失敗不儲存未完成檔案，覆寫既有 CLI 目的檔案需要 `--overwrite`。原生系列（桌面、Linux、Android、OpenWrt）支援此功能，瀏覽器擴充套件不提供檔案傳輸。下載驗證憑證，拒絕內嵌帳密與 HTTPS 降級，最多跟隨五次重新導向。

下載不沿用管理伺服器的 `--insecure`。

## 類 curl 的 HTTP 請求

在裝置 HTTP 請求頁貼上 curl，Console 傳送密封請求，由所選 Agent 執行並回傳狀態碼、耗時、標頭與本文。支援 `-X/--request`、`-H/--header`、`-d/--data`、`--data-raw`、內嵌 `--data-binary`、`--json`、`-I/--head`、`-L/--location`、`-m/--max-time`、`--url`；不執行 shell 或讀取 `@file`。原生 Agent 無需安裝 curl。擴充套件需要網站權限、不攜帶瀏覽器 Cookie，拒絕禁止標頭；Chromium 隱藏的重新導向會提示使用最終網址。唯讀權限不可請求。請求本文上限 256 KiB、逾時上限 120 秒；原生回應最多 1 MiB、擴充套件 128 KiB，超出會標示截斷。二進位或大檔請使用網路檔案下載。

密封訊息為 `net_req`。瀏覽器能力：`net`。CLI 對應指令：`remote-cli net DEVICE http URL -X POST -H 'Content-Type: application/json' -d '{"message":"hello"}'`

```sh
curl -X POST 'https://example.com/api' -H 'Content-Type: application/json' --data-raw '{"message":"hello"}'
```

## 區域網控制連接埠

區域網控制預設關閉，預設 TCP 連接埠為 **7277**。僅在可信區域網中啟用。啟用前裝置必須已經固定工作區根（`remote-agent seal root`，或先連上 Exchange 完成 TOFU）。沒有區域網訪問令牌。不要把連接埠轉發到公網。

在現有 Agent JSON 設定中新增：

```json
{
  "lan_enabled": true,
  "lan_port": 7277
}
```

保留設定中原有的 `server`、`device_id` 和 `token` 欄位。也可使用 `--lan-enabled`、`--lan-port`，或 `REMOTE_LAN_ENABLED`、`REMOTE_LAN_PORT`。未固定工作區根時，啟用 LAN 會拒絕啟動。

桌面設定頁和 LuCI 設定頁均有開關。修改後重新啟動 Agent；桌面設定頁要求先停止連線再修改。關閉開關並重啟後，不再監聽此連接埠。程式不會自動建立防火牆放行規則。

CLI 直連單獨寫設定，不要用 `login`（它要求非空令牌）。`server` 填裝置的 `http://IP:7277`，`token` 留空，請求不帶 `Authorization`：

```toml
server = "http://192.168.1.20:7277"
token = ""
```

用 `REMOTE_CLI_CONFIG` 指向該檔案可以保留另一份雲端登入。密封身分和授權快取放在這份設定所在目錄：`seal-grants.json` 中的離線 grant，以及 `seal-chains.json` 中根簽發在前的憑證鏈。所有裝置操作只開啟密封會話，包括裝置卡片帶 `local` 或區域網地址上 `/api/auth/me` 回傳 401 的直連裝置。Agent 不簽發、不續簽這些授權。雲端離線時只能使用快取中仍有效的根鏈授權。`sessions` 和 `session-kill` 不可用：區域網沒有會話目錄，裝置會話仍由 Exchange 管理。

直連只暴露本機裝置。外層只接受私有、鏈路本機或迴環地址，並校驗 Origin。`GET /api/devices` 在透過這些檢查後只回傳裝置 ID 和啟動密封握手所需的 `seal_key` / `seal_mode`。`GET /api/auth/me` 在密封握手之前不回傳操作員身分。`GET /ws/operator` 只接受密封會話，不提供明文相容路徑。

用戶端在 `open_sealed` 的 hello 裡內聯提交操作員公鑰證明，以及上述離線快取的 grant（`hello.grant`）和可選憑證鏈（`hello.chain`，根簽發的在前）。裝置用與 Exchange 路徑相同的規則核對本機根、裝置範圍和 view/manage，會話內容保持密封。網頁控制台仍透過 Exchange 連線裝置。預設監聽 IPv4 所有介面；雲端離線時仍可使用。LAN 繫結失敗會記錄錯誤，雲端重連繼續執行。

## 迴歸驗證

```sh
python scripts/file-transfer-smoke.py --agent target/debug/remote-agent --cli target/debug/remote-cli
python scripts/agent-ui-smoke.py --agent target/debug/remote-agent --platform linux
```

需要 Python 3.11+ 與 `websockets`。Windows 使用 `.exe` 路徑和 `--platform windows`。測試使用臨時設定與檔案，不修改現有登入或裝置。
