当前位置: 首页 > 科技观察

Koa2的文件上传下载

时间:2023-03-19 18:17:37 科技观察

上传下载在web应用中相当常见,无论是图片还是其他文件。在Koa中,有很多中间件可以帮助我们快速实现功能。文件上传在前端上传文件,我们都是通过表单上传的,上传的文件不能像普通参数一样通过服务端的ctx.request.body获取到。我们可以使用koa-body中间件来处理文件上传,它可以将请求体放入ctx.request中。//app.jsconstkoa=require('koa');constapp=newkoa();constkoaBody=require('koa-body');app.use(koaBody({multipart:true,formidable:{maxFileSize:200*1024*1024//设置上传文件大小限制,默认为2M}}));app.listen(3001,()=>{console.log('koaislisteningin3001');})使用中间件后即可使用在ctx.request.body.files中获取上传的文件内容。需要注意的是设置了maxFileSize,否则一旦上传的文件超过默认限制就会报错。接收到文件后,我们需要将文件保存到目录中,并返回一个url给前端。node中的流程是创建可读流constreader=fs.createReadStream(file.path)创建可写流constwriter=fs.createWriteStream('upload/newpath.txt')通过将可读流写入可写流管道reader.pipe(writer)constrouter=require('koa-router')();constfs=require('fs');router.post('/upload',async(ctx){constfile=ctx.request.body.files.file;//获取上传的文件constreader=fs.createReadStream(file.path);//创建可读流context=file.name.split('.').pop();//获取上传文件的扩展名constupStream=fs.createWriteStream(`upload/${Math.random().toString()}.${ext}`);//创建可写流reader.pipe(upStream);//写入thereadablestreamthroughthepipelineEnterawritablestreamreturnctx.body='uploadedsuccessfully';})这种方法适用于上传图片,文本文件,压缩文件等文件下载koa-send是一个静态文件服务的中间件,可以用来实现文件下载功能。constrouter=require('koa-router')();constsend=require('koa-send');router.post('/download/:name',async(ctx){constname=ctx.params.name;constpath=`upload/${name}`;ctx.attachment(path);awaitsend(ctx,path);})前端下载有两种方式:window.open和表单提交。这里使用了一个更简单的window.open。立即下载wherewindow.open默认为打开一个新窗口,闪烁它然后关闭它,这对用户来说不是一个好的体验。你可以添加第二个参数window.open('/download/1.png','_self');这样就会在当前窗口直接下载。不过这是用url替换当前页面,会触发beforeunload等页面事件。如果你的页面监听了这个事件,做了一些操作,就会产生影响。那么你也可以使用一个隐藏的iframe窗口来达到同样的效果。立即下载批量下载批量下载和单次下载没有区别,多下载几次即可。这真的没问题。如果把这么多文件打包成一个压缩包,然后只下载这个压缩包,岂不是更好的体验?Filepackagingarchiver是Node.js中一个可以实现跨平台打包的模块,支持zip和tar两种格式。constrouter=require('koa-router')();constsend=require('koa-send');constarchiver=require('archiver');router.post('/downloadAll',async(ctx){//will打包文件列表constlist=[{name:'1.txt'},{name:'2.txt'}];constzipName='1.zip';constzipStream=fs.createWriteStream(zipName);constzip=archiver('zip');zip.pipe(zipStream);for(leti=0;i