自己动手搞一个下载站?我踩过的那些坑值得一看
下载站这事,我当初想得太简单了
去年公司财务老张天天找我,说亿企财税那个安装包每次都要去官网翻半天,他手底下几个小姑娘三天两头下载错版本。我就不信邪,想着不就是搭个下载站嘛,自己搞一个,把软件和教程都放上去,大家都方便。结果这一踩坑,就踩了大半年。
一开始我直接在本地搭了个静态页面,用的最简单的 HTML,放个按钮,点本页下载按钮就能拿到安装包。第一版上线的时候我还挺得意,页面清爽,下载链接直接指向我在腾讯云上的对象存储。结果用了两周就出问题了——老张跟我说他们下的安装包报毒,我赶紧看了看,原来是我用的那个对象存储链接被某些浏览器给拦截了,因为不是 HTTPS 的。
我连夜买了 SSL 证书,把链接全换成 HTTPS,以为万事大吉。结果第二天老张又来了,说下载到一半断了,好几个文件是坏的。我一查,是我本地上传的时候没做完整性校验,有的文件上传只传了三分之一就停了。那段时间我简直像个网管,天天帮他们重传文件。
亿企财税安装包到底该怎么放
后来我想明白了,下载站的核心是文件管理,不能跟我一开始那样随便扔。我专门去研究了一下官方的分发方式,发现人家都是分版本、分系统、分架构来放文件的。比如亿企财税有 Windows 版和 Mac 版,Windows 版里面还分 32 位和 64 位,Mac 版又有 Intel 芯片和 M 芯片两种,你要是混在一起,别人下载了装不上,就是你的锅。
我现在的做法是先在服务器上建好目录结构,比如 /soft/yqcs/win64/、/soft/yqcs/win32/、/soft/yqcs/mac-intel/、/soft/yqcs/mac-m1/ 这样。每个目录下再按版本号建子文件夹,比如 v2.4.1、v2.5.0。这么做的好处是,如果用户问我现在最新版是不是有 bug,我可以直接到对应的版本目录里看一眼更新日志,不用去翻乱七八糟的聊天记录。
还有一点很重要:每个文件上传完了,必须算一遍 MD5 或者 SHA256,然后在下载按钮旁边把校验值贴出来。我吃过亏,有一回老张下载了一个亿企财税的安装包,双击安装到一半弹窗说文件损坏,后来发现是我上传的时候网络波动导致文件不完整,校验值对不上就露馅了。从那以后我养成习惯,上传完立即在终端里跑一下 sha256sum,比对没问题了才上线。
点本页下载按钮后,用户到底看到了什么
以前我觉得只要放个按钮就完了,后来发现事情没那么简单。用户的浏览器不一样,下载体验差很多。比如有的用户用的是 IE 或者是旧的 Edge,点本页下载按钮会直接弹出一个下载框,但文件名是乱码,因为服务器没正确设置 Content-Disposition。
这个坑我踩过。我一开始用 Nginx 直接 serve 静态文件,默认情况下中文文件名会变成一串百分号加数字,用户下下来看到 exe 名字是 %E4%BA%BF%E4%BC%81%E8%B4%A2%E7%A8%8E_2.5.0.exe,直接懵了。后来我在 Nginx 里加了一行配置:add_header Content-Disposition 'attachment; filename="亿企财税安装包_2.5.0.exe"'; 当然这个写法只对单个文件管用,更通用的做法是在后端生成下载链接时动态设置。
另外还得考虑大文件下载的情况。亿企财税的安装包现在越来越大,尤其是 Mac 版,动不动就 300MB 往上。要是用户网速慢,下载到 80% 断了,重新来一遍很崩溃。我后来给每个下载链接加了断点续传的支持,这个主要靠服务器端的 Accept-Ranges 头,还有客户端用支持断点续传的下载工具。我在页面上多写了一行小字:推荐使用 IDM 或迅雷下载,或者直接右键链接用浏览器自带的下载管理。
下载站也要防着点爬虫和盗链
一开始我没想防盗链的事,结果上线第三个月,有一天我登录服务器一看,带宽跑满了,流量超标了一大截。我查了下日志,发现有好几个 IP 在疯狂下载我一个文件,下载次数比我所有正经用户加起来还多几十倍。那些人大概率是爬虫,或者有人直接把我下载链接贴到公共论坛上去了。
我赶紧研究防盗链。最简单的办法是限制 Referer,只允许我自己的域名发起的请求能拿到文件。Nginx 里这样写:
if ($http_referer !~* "^http(s)?://(www\.)?我的站点域名.com") { return 403; }
但是这个方法不完美,因为 Referer 可以伪造。后来我又加了个 Token 验证,就是在生成下载链接时,用当前时间戳加一个秘钥算出一个签名,附带在 URL 里,比如 https://down.我的站点.com/亿企财税_2.5.0.exe?token=abc123&expire=20251231。签名过期了或者不对,就返回 404。这个逻辑写在后端 PHP 或者 Node 里都不难,我花了半天写了个小工具,现在每次上传完新版本,自动生成带签名的链接,然后发布到下载页面上。
还有一个我后来才注意到的细节:别让搜索引擎索引了你的安装包文件。我在 robots.txt 里把 /soft/ 目录 disallow 了,又在 Nginx 里对 .exe、.dmg、.zip 这些扩展名加了 deny all,只有带合法 token 的请求才能过。不然 Google 爬到你服务器上一个 500MB 的文件,白占带宽和索引额度。
页面内容写得好,能少接一半客服电话
有些用户下载完不知道装哪个版本,或者装完后不知道怎么激活,就会来问我。我一开始想着发个文档链接,但后来发现很多人压根不看文档。我就把常见问题和操作步骤直接写在下载按钮旁边。
比如我专门写了一段话:如果你是 Windows 10 或 Windows 11 的 64 位系统,直接点本页下载按钮,下载完成后双击安装,安装过程中会弹窗提示选择安装路径,建议不要装到中文目录,否则可能报错。如果你用的是 Mac,先看看你的电脑是 Intel 还是 M 芯片,点对版本后下载,安装后第一次打开要去系统偏好设置里允许来自 App Store 和被认可的开发者,不然会弹窗说无法打开。
就这么几句大白话,加上几个截图,客服咨询量降了至少一半。老张手下的财务小姑娘们看完自己就搞定了,很少再跑来问我。
还有一个很重要的信息是版本说明。每次更新版本,我都会在下载按钮下方贴一个更新日志的摘要,比如:版本 2.5.0 修复了导出 Excel 时偶尔崩溃的问题,优化了大批量发票导入的速度。用户一看就知道自己该不该马上更新。以前我不贴这个,有人用旧版本出了 bug 转头怪我给的安装包不行。
那些年我备份和测试踩过的坑
做下载站最怕的就是你上传了一个出错的版本,用户下载了装不上,然后你还没保留旧版。我有过一次惨痛的教训:有一次我在服务器上把亿企财税从 2.4.0 升级到 2.5.0,上传完就把旧版的文件夹删了。结果 2.5.0 发布后两小时就有用户反馈安装后点启动没反应,我赶紧去查,发现是我打包时漏了一个运行库文件。但是旧版已经被我删了,老张那边的财务还在等软件用,我只能临时从历史邮件里翻出旧版安装包重新传上去,折腾了一下午。
从那以后我养成了几个习惯:服务器上每个版本至少保留三个历史版本,比如 2.4.0、2.4.1、2.5.0 同时存在,用户可以在页面上的下拉菜单里选择历史版本下载;上传新版本之前,在测试机上跑一遍完整安装流程,确认能正常运行再发布;发布后 24 小时内不删旧版本,万一翻车了能快速回滚。
还有测试环境的问题。我一开始信誓旦旦说自己的测试机是 Windows 10 专业版 64 位,结果老张手下一台电脑是 Windows 11 家庭版,装了亿企财税后总提示缺少 .NET Framework 组件。我后来在测试的时候找了四台不同系统的电脑:Win10 64、Win11 64、Mac Intel、Mac M1,每个版本都跑一遍安装和基础功能。虽然累,但确实少了很多奇葩的兼容性问题。
维护下载站最怕的是懒得更新
说句实话,做下载站最大的坑不是技术,而是懒惰。一开始新鲜,三天两头更新版本、写更新日志、回答用户问题。过了几个月,热情退了,新版本出来了也不及时上传,老版本有 bug 也不修复。最后用户发现官网的版本比我的站还新,就不来了。
我现在给自己定了个规矩:亿企财税官方发布新版本后的 24 小时内,我必须把安装包下载下来,算好校验值,上传到服务器,更新页面上的版本号和发布说明。超过时间没更新,就给自己罚款 50 块存进团队红包里。这个方法挺管用,至少现在我还没被罚款过。
还有一点:下载站的页面要定期检查链接是否失效。有一次我发现某个老版本的链接居然返回 404,查日志发现是之前清理服务器时误删了一个文件夹,幸好用户没在这个时候下载。我现在每个月 1 号会用脚本扫一遍所有下载链接,返回不是 200 的记录自动发邮件提醒我。
最后想说,做一个下载站不难,但做好一个下载站真的需要持续投入。如果你只是三分钟热度,不如直接用官方渠道,省得坑自己也坑用户。如果真想搞,就认真搞,别让点本页下载按钮变成点本页报错按钮。