Sails.js(v0.12)应用中如何将服务器文件下载至客户端?
嗨,我来帮你搞定Sails.js v0.12里的文件下载问题!你提到的两个思路其实都能落地,我给你详细拆解下靠谱的实现方式:
方案一:通过静态文件服务直接访问(对应你的第一个思路)
你想让用户通过URL下载文件的思路没问题,只是默认情况下Sails只会暴露assets目录下的静态文件,你的downloads目录不在这个范围内,所以需要手动配置静态路由:
配置静态中间件:
打开config/http.js,找到customMiddleware选项,添加Express的静态文件服务中间件,把downloads目录映射到一个URL路径:var express = require('express'); var path = require('path'); module.exports.http = { middleware: { customMiddleware: function(app) { // 把myApp/downloads目录映射到 /public-downloads 路径下 app.use('/public-downloads', express.static(path.join(__dirname, '../downloads'))); } } };这里用
/public-downloads而不是直接用/downloads是为了避免和业务路由冲突,你可以根据自己的需求调整。用户下载方式:
现在用户只要拿到完整的文件名(比如uuid-filename.ext),就可以通过http://你的域名/public-downloads/uuid-filename.ext直接下载文件了。
⚠️ 注意:如果这些文件需要权限验证(比如只有登录用户才能下载),就不能用这种直接暴露静态文件的方式,得用下面的控制器方案。
方案二:通过控制器流式传输文件(对应你的第二个思路)
你以为Sails没有类似Express的res.download()?其实Sails v0.12的res对象是继承自Express的,res.download()是可以直接用的!另外你提到的res.attachment()也能配合使用,下面是具体实现:
创建文件下载控制器:
在api/controllers/下新建FileController.js,写一个download动作:module.exports = { download: function(req, res) { // 获取请求中的文件名参数 var filename = req.param('filename'); // 拼接完整的文件路径 var filePath = require('path').join(sails.config.appPath, 'downloads', filename); var fs = require('fs'); // 先检查文件是否存在 fs.access(filePath, fs.constants.R_OK, function(err) { if (err) { return res.notFound('请求的文件不存在'); } // 方式1:直接用res.download(),自动处理下载头和流式传输 res.download(filePath, function(err) { if (err) { sails.log.error('文件下载失败:', err); return res.serverError('下载出错,请稍后重试'); } }); // 方式2:用res.attachment() + res.sendFile()(自定义下载文件名时用) // 如果想让用户下载时看到的文件名不是uuid开头的,比如改成"report.pdf" // res.attachment('report.pdf'); // res.sendFile(filePath, function(err) { // if (err) { // sails.log.error('文件下载失败:', err); // return res.serverError('下载出错,请稍后重试'); // } // }); }); } };配置路由:
打开config/routes.js,添加一条路由映射:'GET /download/:filename': 'FileController.download'使用方式:
用户访问http://你的域名/download/uuid-filename.ext就会触发文件下载,而且这个方式可以很方便地在控制器里添加权限验证逻辑(比如检查用户是否登录、是否有权限下载该文件)。
额外注意事项
- 路径安全:一定要用
path.join()拼接路径,避免用户通过构造恶意文件名进行路径遍历攻击;另外可以对filename参数做格式验证(比如检查是否符合uuid-*.ext的格式)。 - 文件权限:确保运行Sails的进程有读取
downloads目录的权限,不然会出现文件读取失败的错误。 - 错误处理:记得处理文件不存在、读取失败等异常情况,给用户返回友好的提示。
内容的提问来源于stack exchange,提问作者Austin E

