用gin实现局域网文件共享完全可行,但需避免staticfs暴露目录导致的安全风险,应通过post上传+带id的get下载(c.file)实现安全共享,并注意formfile参数名匹配、路径安全拼接及调整maxmultipartmemory。

直接说结论:用 Gin 实现局域网简易文件共享系统完全可行,且比写原生 net/http 更快上手、更少出错;但关键不在“能不能传”,而在“怎么避免传完就 404”“怎么让手机扫个码就能下”“怎么不让别人删你硬盘”。
为什么不用 gin.StaticFS 直接暴露目录
很多人一上来就想用 r.StaticFS("/files", http.Dir("./uploads")) 把上传目录挂成静态服务——这确实能下载,但问题一堆:
- 目录遍历漏洞:访问
/files/../../etc/passwd可能直接读到系统文件(Gin 默认不拦截) - 无权限控制:任何人知道 URL 就能列目录、下载所有文件
- 无文件元信息:浏览器点开只弹保存框,不知道文件名、大小、类型
- 上传和下载路径分离:
StaticFS不处理 POST,还得另写上传路由
正确做法是:上传走 POST 接口,下载走带签名或 ID 的 GET 接口(比如 /download/:id),用 c.File() 流式返回,而不是暴露整个目录。
c.FormFile 和 c.SaveUploadedFile 的坑
这两个函数看着简单,实际藏着三个高频翻车点:
-
c.FormFile("file")的参数名必须和 HTML 表单里<input type="file" name="file">的name完全一致,大小写敏感,多一个空格都报http: no such file -
c.SaveUploadedFile的目标路径不能含非法字符(如../),否则可能被路径穿越;建议用filepath.Join("uploads", securefilename)拼接,并提前os.MkdirAll("uploads", 0755) - 默认内存限制是 32MB,超限会直接 panic;需在
gin.Default()后加r.MaxMultipartMemory = 1024 (即 1GB),否则大文件上传直接 500
让手机扫码就能下载的关键:生成短链接 + 文件 ID
局域网共享最常用场景是手机拍电脑屏幕上的二维码下载文件。这就要求:
- 每个上传文件生成唯一 ID(如 UUID 或时间戳+随机数),存进 map 或本地 JSON 文件
- 提供
GET /share/:id路由,查 ID → 找到真实文件名 → 用c.Header("Content-Disposition", "attachment; filename="+url.PathEscape(realName))设置下载名 - 前端上传成功后,返回
{"share_url": "http://192.168.1.100:8080/share/abc123"},再用 qrcode.js 生成二维码
别用文件名做路由(/download/hello.jpg),容易冲突、不安全、URL 编码麻烦。
局域网部署时最容易被忽略的三件事
开发时 r.Run(":8080") 能跑,扔到局域网就失效,通常卡在这三点:
- Gin 默认只监听
127.0.0.1,要改成r.Run("0.0.0.0:8080")才能被其他设备访问 - 麒麟/Ubuntu 等系统默认开启防火墙,需放行端口:
sudo ufw allow 8080或关闭防火墙临时测试 - 手机浏览器访问时,地址必须写完整 IP,不能写
localhost或127.0.0.1;可用ip addr show | grep "inet " | grep -v "127.0.0.1"快速查本机局域网 IP
上传后文件存在服务器磁盘上,但没人管清理;如果只是临时传个安装包,建议加个定时任务每天清空 uploads/ 下 24 小时前的文件——这个逻辑得自己写,Gin 不管。











