{"id":19456700,"url":"https://github.com/localsend/protocol","last_synced_at":"2026-01-28T10:32:13.799Z","repository":{"id":138849550,"uuid":"585348034","full_name":"localsend/protocol","owner":"localsend","description":"The LocalSend REST API","archived":false,"fork":false,"pushed_at":"2025-02-20T14:47:46.000Z","size":38,"stargazers_count":348,"open_issues_count":5,"forks_count":27,"subscribers_count":11,"default_branch":"main","last_synced_at":"2025-02-20T15:39:50.831Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":null,"has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/localsend.png","metadata":{"files":{"readme":"README-zh-CN.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2023-01-05T00:05:08.000Z","updated_at":"2025-02-20T14:47:52.000Z","dependencies_parsed_at":"2024-07-11T03:27:10.478Z","dependency_job_id":"7a0f3949-4b9e-4370-a9c2-5f1ca67e9406","html_url":"https://github.com/localsend/protocol","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/localsend/protocol","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/localsend%2Fprotocol","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/localsend%2Fprotocol/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/localsend%2Fprotocol/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/localsend%2Fprotocol/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/localsend","download_url":"https://codeload.github.com/localsend/protocol/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/localsend%2Fprotocol/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28844014,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-28T07:39:25.367Z","status":"ssl_error","status_checked_at":"2026-01-28T07:39:24.487Z","response_time":57,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-11-10T17:18:12.419Z","updated_at":"2026-01-28T10:32:13.792Z","avatar_url":"https://github.com/localsend.png","language":null,"funding_links":[],"categories":["网络信息服务","Others"],"sub_categories":["资源传输下载"],"readme":"# LocalSend 协议 v2\n\n[English](./README.md) | **简体中文**\n\n主要为了实现一个不依赖于任何外部服务器的简单 REST 协议。\n\n因为计算机网络比较复杂，因此我们不能假设每种方法都可用。某些设备可能不支持多点广播或不能运行 HTTP 服务器。\n\n就是这个原因，所以这协议尝试用多种方式去发现其他 LocalSend 成员，从而执行发送文件。\n\n该协议只需要一方建立 HTTP 服务器即可运行。\n\n## 目录\n\n- [LocalSend 协议 v2](#localsend-协议-v2)\n  - [目录](#目录)\n  - [1. 默认配置](#1-默认配置)\n  - [2. 指纹](#2-指纹)\n  - [3. 搜寻发现](#3-搜寻发现)\n    - [3.1 UDP 组播](#31-udp-组播)\n    - [3.2 HTTP (传统模式)](#32-http-传统模式)\n  - [4. 文件传输 (HTTP)](#4-文件传输-http)\n    - [4.1 准备工作 (仅元数据)](#41-准备工作-仅元数据)\n    - [4.2 发送文件](#42-发送文件)\n    - [4.3 取消](#43-取消)\n  - [5. 反向文件传输 (HTTP)](#5-反向文件传输-http)\n    - [5.1 浏览器 URL](#51-浏览器-url)\n    - [5.2 接收请求](#52-接收请求)\n    - [5.3 接收文件](#53-接收文件)\n  - [6. 其他 API](#6-其他-api)\n    - [6.1 信息](#61-信息)\n  - [7. 枚举](#7-枚举)\n    - [7.1 设备类型](#71-设备类型)\n\n## 1. 默认配置\n\nLocalSend 不需要特定的端口或组播地址，而是提供默认配置。\n\n如果端口/地址不可用，可以在应用程序中修改配置。\n\n默认组播地址是 224.0.0.0/24，因为某些 Android 设备禁止其他组播组。\n\n**UDP组播**\n\n- 端口: 53317\n- 地址: 224.0.0.167\n\n**HTTP (TCP)**\n\n- 端口: 53317\n\n## 2. 指纹\n\n指纹用于区分设备。\n\n使用 HTTPS 加密时，证书的 SHA-256 哈希值作为指纹。\n\n关闭 HTTPS 加密时，用随机字符串作为指纹。\n\n## 3. 搜寻发现\n\n### 3.1 UDP 组播\n\n**通知**\n\n在应用程序启动时，会发送以下消息到组播地址：\n\n```json5\n{\n  \"alias\": \"Nice Orange\",\n  \"version\": \"2.0\", // 协议版本（major.minor）\n  \"deviceModel\": \"Samsung\", // nullable\n  \"deviceType\": \"mobile\", // mobile | desktop | web | headless | server, nullable\n  \"fingerprint\": \"随机字符串\",\n  \"port\": 53317,\n  \"protocol\": \"https\", // http | https\n  \"download\": true, // 下载 API（5.2 和 5.3）是否激活（可选，默认为 false）\n  \"announce\": true\n}\n```\n\n**返回**\n\n其他 LocalSend 成员会收到到此消息并回复各自的设备信息。\n\n首先，向原设备发送 HTTP/TCP 请求：\n\n`POST /api/localsend/v2/register`\n\n```json5\n{\n  \"alias\": \"Secret Banana\",\n  \"version\": \"2.0\",\n  \"deviceModel\": \"Windows\",\n  \"deviceType\": \"desktop\",\n  \"fingerprint\": \"随机字符串\", // 在 HTTPS 模式下被忽略\n  \"port\": 53317,\n  \"protocol\": \"https\",\n  \"download\": true, // 下载 API（5.2 和 5.3）是否激活（可选，默认为 false）\n}\n```\n\n另外，成员还可以使用 UDP 组播消息进行响应。\n\n```json5\n{\n  \"alias\": \"Secret Banana\",\n  \"version\": \"2.0\",\n  \"deviceModel\": \"Windows\",\n  \"deviceType\": \"desktop\",\n  \"fingerprint\": \"随机字符串\",\n  \"port\": 53317,\n  \"protocol\": \"https\",\n  \"download\": true,\n  \"announce\": false,\n}\n```\n\n`fingerprint` 仅用于区分自身设备。\n\n只有当 `announce` 为 `true` 时，才会触发响应。\n\n### 3.2 HTTP (传统模式)\n\n当组播不成功时应使用此方法。\n\n向本地所有 IP 地址发送此请求来发现设备。\n\n`POST /api/localsend/v2/register`\n\n请求：\n\n```json5\n{\n  \"alias\": \"Secret Banana\",\n  \"version\": \"2.0\", // 协议版本（major.minor）\n  \"deviceModel\": \"Windows\",\n  \"deviceType\": \"desktop\",\n  \"fingerprint\": \"随机字符串\", // 在 HTTPS 模式下被忽略\n  \"port\": 53317,\n  \"protocol\": \"https\", // http | https\n  \"download\": true, // 下载 API（5.2 和 5.3）是否激活（可选，默认为 false）\n}\n```\n\n返回：\n\n```json5\n{\n  \"alias\": \"Nice Orange\",\n  \"version\": \"2.0\",\n  \"deviceModel\": \"Samsung\",\n  \"deviceType\": \"mobile\",\n  \"fingerprint\": \"随机字符串\", // 在 HTTPS 模式下被忽略\n  \"download\": true, // 下载 API（5.2 和 5.3）是否激活（可选，默认为 false）\n}\n```\n\n## 4. 文件传输 (HTTP)\n\nHTTP传输是默认方式。\n\n接收方作为 HTTP 服务器。\n\n发送方（即 HTTP 客户端）将文件发送到 HTTP 服务器。\n\n### 4.1 准备工作 (仅元数据)\n\n仅将元数据发送给接收方。\n\n接收方将决定该请求是否被接受、部分接受或拒绝。\n\n`POST /api/localsend/v2/prepare-upload`\n\n请求：\n\n```json5\n{\n  \"info\": {\n    \"alias\": \"Nice Orange\",\n    \"version\": \"2.0\", // 协议版本 (major.minor)\n    \"deviceModel\": \"Samsung\", // 可为空\n    \"deviceType\": \"mobile\", // mobile | desktop | web | headless | server, 可为空\n    \"fingerprint\": \"随机字符串\", // 在 HTTPS 模式下被忽略\n    \"port\": 53317,\n    \"protocol\": \"https\", // http | https\n    \"download\": true, // 下载 API (5.2 和 5.3) 是否激活 (可选，默认为 false)\n  },\n  \"files\": {\n    \"文件ID\": {\n      \"id\": \"文件ID\",\n      \"fileName\": \"我的图片.png\",\n      \"size\": 324242, // bytes\n      \"fileType\": \"image/jpeg\",\n      \"sha256\": \"*sha256哈希值*\", // 可为空\n      \"preview\": \"*预览数据*\" // 可为空\n    },\n    \"另一个文件ID\": {\n      \"id\": \"另一个文件ID\",\n      \"fileName\": \"另一个图片.jpg\",\n      \"size\": 1234,\n      \"fileType\": \"image/jpeg\",\n      \"sha256\": \"*sha256哈希值*\",\n      \"preview\": \"*预览数据*\"\n    }\n  }\n}\n```\n\n返回：\n\n```json5\n{\n  \"sessionId\": \"我的会话ID\",\n  \"files\": {\n    \"文件ID\": \"文件Token\",\n    \"另一个文件ID\": \"另一个文件Token\"\n  }\n}\n```\n\nErrors 错误代码\n\n| HTTP 代码 | 信息                |\n| --------- | ------------------- |\n| 204       | 完成 (无需传输文件) |\n| 400       | 无效请求体          |\n| 403       | 拒绝                |\n| 500       | 接收器未知错误      |\n\n### 4.2 发送文件\n\n文件传输。\n\n使用来自 `/prepare-upload` 的 `sessionId`、`fileId` 及其特定于文件的 `token`。\n\n这请求路径可以同时调用。\n\n`POST /api/localsend/v2/upload?sessionId=我的会话ID\u0026fileId=文件ID\u0026token=文件Token`\n\n请求：\n\n```text\n二进制数据\n```\n\n返回：\n\n```text\n无响应体\n```\n\nErrors 错误代码\n\n| HTTP 代码 | 信息               |\n| --------- | ------------------ |\n| 400       | 参数缺失           |\n| 403       | 无效令牌或 IP 地址 |\n| 409       | 被其他会话阻止     |\n| 500       | 接收器未知错误     |\n\n### 4.3 取消\n\n当发送方希望取消会话时，可用此请求路径。\n\n使用 `/send-request` 中的 `sessionId`。\n\n`POST /api/localsend/v2/cancel?sessionId=我的会话ID`\n\n返回：\n\n```text\n无响应体\n```\n\n## 5. 反向文件传输 (HTTP)\n\nHTTP方式是当接收方无法使用 LocalSend 时应使用的备用方法。\n\n发送方设置一个 HTTP 服务器，通过提供 URL 将文件发送给其他成员。\n\n然后接收方使用给定的 URL 打开浏览器并下载文件。\n\n需要注意的是，由于浏览器拒绝自签名证书，因此使用未加密的 HTTP 协议。\n\n### 5.1 浏览器 URL\n\n接收方可以在浏览器中打开以下网址来下载文件。\n\n```text\nhttp://\u003c发送者ip\u003e:\u003c发送者端口\u003e\n```\n\n### 5.2 接收请求\n\n向发送方发送请求以获取文件元数据列表。\n\n下载方可以添加 `?sessionId=我的会话ID`。此时，如果是同一个会话，则接受该请求。\n\n如果用户刷新浏览器页面，则需要这样操作。\n\n`POST /api/localsend/v2/prepare-download`\n\n请求：\n\n```text\n无请求体\n```\n\n返回：\n\n```json5\n{\n  \"info\": {\n    \"alias\": \"Nice Orange\",\n    \"version\": \"2.0\",\n    \"deviceModel\": \"Samsung\", // 可为空\n    \"deviceType\": \"mobile\", // mobile | desktop | web | headless | server, 可为空\n    \"fingerprint\": \"随机字符串\", //  在 HTTPS 模式下被忽略\n    \"download\": true, // 下载 API (5.2 和 5.3) 是否激活 (可选，默认为 false)\n  },\n  \"sessionId\": \"mySessionId\",\n  \"files\": {\n    \"文件ID\": {\n      \"id\": \"文件ID\",\n      \"fileName\": \"我的图片.png\",\n      \"size\": 324242, // bytes\n      \"fileType\": \"image/jpeg\",\n      \"sha256\": \"*sha256哈希值*\", // 可为空\n      \"preview\": \"*预览数据*\" // 可为空\n    },\n    \"另一个文件ID\": {\n      \"id\": \"另一个文件ID\",\n      \"fileName\": \"另一个图片.jpg\",\n      \"size\": 1234,\n      \"fileType\": \"image/jpeg\",\n      \"sha256\": \"*sha256哈希值*\",\n      \"preview\": \"*预览数据*\"\n    }\n  }\n}\n```\n\n### 5.3 接收文件\n\n文件传输。\n\n使用 `/receive-request` 中的 `sessionId` 和 `fileId`。\n\n这请求路径可以同时调用。\n\n`GET /api/localsend/v2/download?sessionId=我的会话ID\u0026fileId=文件ID`\n\n请求：\n\n```text\n无请求体\n```\n\n返回：\n\n```text\n二进制数据\n```\n\n## 6. 其他 API\n\n### 6.1 信息\n\n这是一条以前用于发现的旧连接。 它已被替换为“/register”，这是一种双向发现。\n\n现在该路由应该仅用于调试。\n\n`GET /api/localsend/v2/info`\n\n返回：\n\n```json5\n{\n  \"alias\": \"Nice Orange\",\n  \"version\": \"2.0\",\n  \"deviceModel\": \"Samsung\", // 可为空\n  \"deviceType\": \"mobile\", // mobile | desktop | web | headless | server, 可为空\n  \"fingerprint\": \"随机字符串\",\n  \"download\": true, // 下载 API (5.2 和 5.3) 是否激活 (可选，默认为 false)\n}\n```\n\n## 7. 枚举\n\n在这项目中，枚举用于定义某些字段的可能值。\n\n### 7.1 设备类型\n\n设备类型仅用于 UI 使用，例如显示图标。\n\n各种设备类型的协议都一样。\n\n| 值       | 描述                            |\n| -------- | ------------------------------- |\n| mobile   | 移动设备 (Android, iOS, FireOS) |\n| desktop  | 桌面 (Windows, macOS, Linux)    |\n| web      | 网页浏览器 (Firefox, Chrome)    |\n| headless | 在终端运行的无图形用户界面程序  |\n| server   | 全天候运行的（自托管）云服务    |\n\n如有枚举外的值，都返回 `desktop` 类型。\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flocalsend%2Fprotocol","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Flocalsend%2Fprotocol","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flocalsend%2Fprotocol/lists"}