dsh-phone-drop
Identified局域网手机直传:电脑屏幕出二维码,手机扫码拍照/扫描直接落进电脑文件夹,不经过任何隧道。DSH 插件。
dsh-phone-drop
手机一拍,电脑就有。
手机和电脑连同一个 Wi-Fi,手机浏览器打开一个地址,拍照或选图 → 想扫描就勾一下「文档模式」,自动裁边转黑白 → 落进电脑的一个文件夹。全程局域网直连,不经过任何隧道,毫秒级。
默认什么都不改:不勾选时,手机上拍的照片原样传到电脑,字节都不动(大小、格式、EXIF 全是原样)。
为什么需要它
把手机里的图弄进电脑,常见路子都很别扭:
- 微信/QQ 传文件:压图、要登录、还要手动另存。
- 云盘:上传再下载,两张图等半天。
dsh web自带的隧道:请求要绕一圈公网,每张图几秒钟,而且慢得莫名其妙——手机 CPU 和网速都没跑满,时间全花在跨境往返上。
这个插件走的是最短路:手机和电脑本来就在同一个路由器下,直接连过去就行。
装
dsh plugin install dsh-phone-drop
或者作为 bundle 加进 profile 的 package.json:
{
"dependencies": { "dsh-phone-drop": "^0.4.1" },
"dsh": { "profile": { "bundles": ["dsh-phone-drop"] } }
}
装完重启宿主,日志里会出现:
dsh-phone-drop: 服务已启动,监听 0.0.0.0:9800,保存到 C:\Users\你\Pictures\dsh-phone-drop
dsh-phone-drop: 手机请打开 http://192.168.1.23:9800
第一次装会弹个设置窗口
npm install -g dsh-phone-drop 装完之后,Windows 上会先弹一个小窗口,让你一次定三件事:
- 照片存到哪儿(默认
图片/dsh-phone-drop,可点「浏览…」另选); - 要不要在桌面建「手机直传」快捷方式;
- 装完要不要立刻打开一次二维码页面。
点「就这样」生效;点「跳过」或直接关窗口,什么都不改,用默认值。以后随时能重开这个窗口:
dsh-phone-drop --setup
或者跳过它:
dsh-phone-drop --no-setup
只有在全局安装(npm install -g)时才会弹;作为别人的依赖被装进去时不弹。这套设置只出现一次,选过的路径会记住,下次启动不再问。
新版 npm 会拦 postinstall(重要):npm 11.16+ 起对「还没被 allowScripts 授权的安装脚本」默认拦截,装的时候会看到一行
npm warn install-scripts 1 package has install scripts not yet covered by allowScripts: dsh-phone-drop@0.4.1, 这时安装弹窗不会自己弹。三条路,任选其一:
- 装的时候带
--allow-scripts=dsh-phone-drop:npm install -g dsh-phone-drop --allow-scripts=dsh-phone-drop- 或者永久放行这个包:
npm config set allow-scripts=dsh-phone-drop --location=user- 什么都不管,装完第一次运行
dsh-phone-drop时照样会弹(CLI 每次启动前都检查「设置过没有」,没设置过就弹同一个窗口)。所以「没弹窗」不等于「没法用」,跑一下命令就行。
用
- 手机连上同一个 Wi-Fi(和电脑同一个路由器,不是流量)。
- 电脑上打开
http://127.0.0.1:9800/qr,屏幕上是一个大二维码。用手机的相机或扫一扫对着它,点弹出来的链接就进去了——不用在手机上敲 IP,也不用记端口。 (也可以在手机浏览器里手动输日志里那个地址,或者问助手「手机怎么传图给你」,它会跑phone_drop工具把地址和二维码念出来。) - 点「📷 拍照」拍一张,或点「🖼 相册 / 文件」挑一张。
- 就这样点「上传图片」 → 原始文件直接落到电脑,不做任何处理。
- 想要扫描件,就先拨开「文档模式」开关:页面立刻把图裁边、转成黑白,还能拖「墨色」滑块调深浅、点「↻ 旋转 90°」摆正,然后按钮会变成「上传扫描件」。
- 文件就出现在电脑的接收目录里,文件名带时间戳。
手机浏览器里那个页面可以「添加到主屏幕」,之后点桌面图标直接进,跟装了 App 一样。
在 DSH 页面里点一个按钮就开
装了插件之后,DSH 侧边栏底部(设置齿轮旁边)会多一个「手机直传」按钮。点它就直接打开二维码页面,不用记 9800 这个端口,也不用收藏链接。
按钮是通过 dsh.client 声明 + lib/client.js 提供的浏览器半边,挂在 sidebar.footer.action 插槽上——这是 root 级、list 类型的插槽,只往后追加一项,不会覆盖别人的入口。
按钮背后是一个只对本机开放的接口:
GET /api/phone-drop/info → { running, dir, port, deskUrl }
它只接受来自回环地址(127.0.0.1 / ::1)的请求,别的来源一律 403;非 GET 返回 405。所以局域网里的手机拿不到这个接口,也不需要它——手机走的是二维码那个页面。
侧边栏按钮是从 0.4.3 开始有的。0.4.2 的 npm 包先发了包、后补的界面,
lib/client.js没进 tarball,所以装 0.4.2 看不到按钮。
扫描是怎么来的(勾上文档模式之后)
手机相机没有对网页开放「文档扫描」模式——那是相机 App 自己的功能,<input type=file capture> 只能拿到一张普通彩色照片。所以扫描这件事由页面自己做:
- 去色:按 Rec.601 亮度转灰度。
- 自适应二值化:每个像素跟它周围 28×28 邻域的平均亮度比,暗过一截就判成墨点。用积分图算局部均值,所以整页 2000px 也只要几十毫秒。这一步是关键——全局阈值在灯光不均时会一半黑一半白,局部阈值不会。
- 去噪:孤零零一个黑点周围没有同伴,判成纸屑丢掉,笔画留着。
- 裁边:先在灰度里估出「这一帧的纸有多亮」(取 90 分位,避免少数暗角或反光带偏),把够亮的像素算作纸面,再按行/列的占用率找出纸的边界,四周留 2% 白边。这一步必须看灰度,不能看二值图——深色桌面上自适应阈值也会把桌面判成白,那样裁出来的框就是整幅画。找不到纸面、或者纸面几乎铺满整幅,就不裁。
三档结果可选:黑白扫描(默认)、灰度增强(对比拉伸,适合铅笔稿)、原图。
整个扫描过程纯前端、不用联网、不需要 HTTPS(局域网 http:// 没有安全上下文,getUserMedia 用不了),也不上传原图——处理完只传最终那张。
配置
在 profile 的 cordis.patch.yml 里覆盖:
- id: phone-drop
config:
port: 9800 # 监听端口
host: '0.0.0.0' # 绑定地址,默认所有网卡
dir: 'D:/手机图片' # 接收目录
token: 'my-secret' # 访问口令,见下
title: '手机直传' # 页面标题
enabled: true # 关掉整行就停
口令
默认没有口令——同一个 Wi-Fi 下的任何设备都能往目录里丢文件。在家里够用,但咖啡馆/宿舍就不合适了。设了 token 之后,除 /health 外每个路由都要带 ?k=口令,页面上传也一样;比对用的是定长哈希的常数时间比较,不会因为提前返回泄露长度。二维码里会自动带上口令。
换存放文件夹
三种办法,效果一样:
- 跟助手说「把手机传图存到 D 盘某某文件夹」,它会调
phone_drop的setdir——下一次拍照就落到新目录,不用重启。 - 直接改
~/.dsh-phone-drop.json里的dir(文件不存在就自己建一个,格式{"dir": "D:/手机图片"})。 - 任何脚本 POST 到
http://127.0.0.1:9800/api/dir,body{"dir": "D:/手机图片"}。
这个覆盖文件优先于 cordis.patch.yml 里的 dir,删掉它就回到配置里的值。之所以单独放一个文件、而不是让插件去改 profile 补丁:那个文件有好几个写者(loader 会重写托管块),插件背着它改只会打架。/api/dir 只接受来自本机回环的请求,手机上改不了别人电脑的落盘位置。命令行 --dir 只管本次运行,不会写进覆盖文件——否则一次试用会永久劫持之后每一次启动。
工具
插件注册了一个 phone_drop 工具,助手可以调用:
action | 作用 |
|---|---|
url | 返回手机上该打开的地址、接收目录 |
qr | 额外返回一段终端字符二维码,可以直接贴进对话里让用户扫 |
recent | 额外返回最近收到的文件名和大小 |
setdir | 换存放文件夹(配 dir 参数) |
这样用户问「手机怎么传图给你」时,助手直接把地址说出来,不用去翻日志。
不开 DSH 也能跑
npx dsh-phone-drop --port 9800 --dir ./收图 --open
同一个服务器,同一个页面,前台跑着,Ctrl+C 停。--open 会直接把二维码页面开到浏览器里。
命令行选项
| 选项 | 作用 |
|---|---|
--port <n> | 监听端口(默认 9800) |
--host <addr> | 绑定地址(默认 0.0.0.0) |
--dir <path> | 本次运行的接收目录(不写进设置文件) |
--token <str> | 访问口令 |
--title <str> | 页面标题 |
--open | 启动后自动打开二维码页面 |
--no-qr | 不在终端打印字符二维码 |
--setup | 打开设置窗口(选目录 / 快捷方式 / 自动打开) |
--no-setup | 跳过首次设置窗口 |
安全边界
- 监听
0.0.0.0是刻意的:这个服务的存在意义就是让手机连进来。它不是 DSH 宿主 webserver——那一个明确拒绝通配地址,因为前面挂着整个远程执行面;这里只有几个路由,没有会话、没有 shell、不碰宿主状态。 - 上限 64 MB/次,超了直接 413 并断流。
- 文件名只取 basename 并清掉 Windows 非法字符,落地永远在配置的目录里,不会被
../带出去;/file?name=先按目录列表核对一遍,再核对解析后的真实路径,两道都过才发。 - 上传内容原样落盘,不执行、不解析;下载时带
x-content-type-options: nosniff,不让浏览器猜类型。 /api/dir(换目录)只允许本机回环调用。- 建议只在可信网络里开;公用网络请设
token。
许可
MIT。二维码编码器内置了 Nayuki 的 qrcode-generator(MIT)的 TypeScript 转译产物。
Comments
Loading…
Similar plugins
by apherchin
手机拍照经局域网一键进 PC 文件夹,DSH 插件面板可配落地目录 | DSH plugin: one-tap photo transfer from phone to a configurable folder on this PC over the LAN, with a config card on the Plugins page.
★ 0
MIT
JavaScript
Oct 4, 2026
dsh plugin --profile web add dsh-photo2dsh-by-lanby swarm-apps
Send files from your DeepSeek Harness agent straight to your phone, and reference what your phone sent back — no account, no public IP, end-to-end encrypted.
★ 4
TypeScript
Aug 24, 2026
dsh plugin --profile web add dsh-swarmdropby Hongjun1-RGB
DSH 插件:在界面里拨一个开关,用手机浏览器继续当前会话(内嵌反向代理 + Cloudflare 隧道 + 微信推送)
★ 1
MIT
JavaScript
Oct 15, 2026
dsh plugin --profile web add dsh-phone-accessby godchen520
DSH 手机/外网远程访问插件:免配置公网隧道 + 局域网 HTTPS 直连 + 自定义公网链接/端口 + 微信机器人
★ 19
↓ 348/wk
MIT
JavaScript
Oct 24, 2026
dsh plugin --profile agent add dsh-web-remoteby ImHaoYuan
DSH 插件:搭建远程控制局域网服务器,手机浏览器直连,也可下载App
★ 0
MIT
JavaScript
Oct 10, 2026
dsh plugin --profile web add dsh-mobile-mirrorby copylee711
DeepSeek Harness 远程控制插件:手机扫码、电脑确认后,用手机浏览器继续会话、审批和管理设置。
★ 3
MIT
TypeScript
Oct 23, 2026
dsh plugin --profile web add @copylee/dsh-remote-control