node实现文件下载
1.方法一:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 | router.post( '/downloadPdf' ,(req,res)=>{ // let { filename,mimeType } = req.body; let { filename,mimeType } = req.query; // var path="public/pdf/5ea56710fb5a2fdad7cabcf3.pdf"; // filename = '02cbc5d9-e10f-4f8d-8fae-304cc609a8f0'; //pdf // filename = '6f3db1f9-e247-4aa5-bca7-93bae62a0079' // mp4 // filename = '6a908990-0c4f-4101-9e9d-4c8b00a8133b' // doc // filename='2055c73b-1b37-40bc-ba50-b6b8ef82e63c' // docx // mimeType='application/pdf'; let type = getType(mimeType); //获取文件后缀名 console.log(filename,mimeType,type); // path = path.join(__dirname, '../public/showPdf/'+filename+'.'+type); path= './public/showPdf/' +filename+ '.' +type; // path="C:\Users\sswc\Desktop\gai2\public\showPdf\02cbc5d9-e10f-4f8d-8fae-304cc609a8f0.pdf" console.log(path); var fileStream = fs.createReadStream(path); var size = fs.statSync(path).size; res.setHeader( 'Content-Type' , mimeType); res.setHeader( 'Content-Disposition' , `attachment;filename=${filename}.${type}`); res.setHeader( 'Content-Length' , size); fileStream.on( 'data' , function (data) { res.write(data, 'binary' ); }); fileStream.on( 'end' , function () { res.end(); console.log( 'The file has been downloaded successfully!' ); }); }) |
2.方法二:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 | router.post( '/downloadPdf' ,(req,res)=>{ // let { filename,mimeType } = req.body; let { filename,mimeType } = req.query; // var path="public/pdf/5ea56710fb5a2fdad7cabcf3.pdf"; // filename = '02cbc5d9-e10f-4f8d-8fae-304cc609a8f0'; //pdf // filename = '6f3db1f9-e247-4aa5-bca7-93bae62a0079' // mp4 // filename = '6a908990-0c4f-4101-9e9d-4c8b00a8133b' // doc // filename='2055c73b-1b37-40bc-ba50-b6b8ef82e63c' // docx // mimeType='application/pdf'; let type = getType(mimeType); //获取文件后缀名 console.log(filename,mimeType,type); // path = path.join(__dirname, '../public/showPdf/'+filename+'.'+type); path= './public/showPdf/' +filename+ '.' +type; // path="C:\Users\sswc\Desktop\gai2\public\showPdf\02cbc5d9-e10f-4f8d-8fae-304cc609a8f0.pdf" console.log(path); fs.readFile(path, (err, data) => { if (err) { throw err } res.setHeader( 'Content-Type' ,mimeType) // 设置文件名 // Content-disposition 是 MIME 协议的扩展,MIME 协议指示 MIME 用户代理如何显示附加的文件 // attachment 以附件形式下载 res.setHeader( 'Content-Disposition' , `attachment; filename=${filename}.${type}`) // 返回数据 res.end(data) }) }) |
上面两种通过node实现得下载代码得方式,获取文件路径需要通过相对路径,不能通过node提供得path取获取路径,如下所示:
1 | path = path.join(__dirname, '../public/showPdf/' +filename+ '.' +type); |
在刚做文件下载时候,我是通过path来获取文件得路径,文件是可以下载得,但是只能下载一次,到第二次下载得时候,path获取路径得时候,会出现问题,导致接口包500得错误。当时耽搁了一整天,也没发现错在那里了,但是我写的下载接口就是只能调用一边,后面我看了看和其他人写的有什么不同,突然间看见是因为path得原因。当我的path通过相对路径获取得时候,下载接口恢复了正常。
注意:我这里得getType()方法是用来获取文件得后缀名得,因为当时我们做得时候,平台支持得文件有很多种形式,为了做各种文件得下载兼容以及更好得取寻找我们需要对应得文件,所以定义了一个方法,用来兼容各种类型得文件,该方法如下所示:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 | // 获取文件得后缀名 function getType(mimeType){ switch (mimeType) { case 'video/x-msvideo' : return 'avi' ; case 'video/x-ms-wmv' : return 'wmv' ; case 'video/x-flv' : return 'flv' ; case 'image/x-ico' : return 'ico' ; case 'image/x-psd' : return 'psd' ; case 'text/csv' : return 'csv' ; case 'text/html' : return 'html' ; case 'text/plain' : return 'txt' ; case 'text/xml' : return 'xml' ; case 'video/mp4' : return 'mp4' ; case 'video/mpeg' : return 'mpg' ; case 'application/x-shockwave-flash' : return 'swf' ; case 'audio/mpeg' : return 'mp3' ; case 'audio/x-ogg' : return 'ogg' ; case 'audio/x-wav' : return 'wav' ; case 'image/jpeg' : return 'jpg' ; case 'image/png' : return 'png' ; case 'image/svg+xml' : return 'svg' ; case 'application/x-mspublisher' : return 'pub' ; case 'application/vnd.visio' : return 'vsd' ; case 'application/vnd.openxmlformats-officedocument.wordprocessingml.document' : return 'docx' ; case 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' : return 'xlsx' ; case 'application/vnd.openxmlformats-officedocument.presentationml.presentation' : return 'pptx' ; case 'application/msword' : return 'doc' ; case 'application/pdf' : return 'pdf' ; case 'application/postscript' : return 'ps' ; case 'application/rtf' : return 'rtf' ; case 'application/vnd.ms-access' : return 'mdb' ; case 'application/vnd.ms-excel' : return 'xls' ; case 'application/vnd.ms-powerpoint' : return 'ppt' ; case 'application/vnd.oasis.opendocument.text' : return 'ott' ; } } |
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现