当前位置: 首页 > 后端技术 > Node.js

Koa从头开始构建上传文件

时间:2023-04-03 13:06:32 Node.js

在日常开发过程中,有很多与图片/文件上传相关的需求,那么如何用Koa来实现呢?前言在前面的课程中提到,Koa框架是一个基于中间件的框架,我们需要的一些功能需要安装相应的中间件库。实现文件上传,有很多插件:koa-bodykoa-bodyparserbusboykoa-multer……这里推荐koa-body!让我们仔细看看吧!之前koa-body使用koa2时,使用koa-bodyparser处理post请求,使用koa-multer进行图片上传。两者结合没有问题,但是koa-multer和koa-route(不是koa-router)存在不兼容的问题。koa-body结合了两者,因此koa-body可以替代它。koa-body的基本使用使用koa2中的koa-body。我使用的是全局导入,而不是路由级别的导入,因为考虑到很多地方都有post请求或者文件上传请求,没必要只在路由级别导入。.依赖安装npmikoa-body-Dapp.jsconstkoaBody=require('koa-body');constapp=newkoa();app.use(koaBody({multipart:true,//支持文件上传编码:'gzip',formidable:{uploadDir:path.join(__dirname,'public/upload/'),//设置文件上传目录keepExtensions:true,//保留文件后缀maxFieldsSize:2*1024*1024,//文件上传大小onFileBegin:(name,file)=>{//文件上传前的设置//console.log(`name:${name}`);//console.log(file);},}}));有用参数npm/koa-body获取文件上传后的信息router.post('/',async(ctx)=>{console.log(ctx.request.files);正文);ctx.body=JSON.stringify(ctx.request.files);});resultsize-文件大小path-文件上传后的目录名-文件类型原名-文件类型lastModifiedDate-最后更新时间为什么选择这个标题,因为很多企业级项目不选择自己存储一些图片文件服务器,为什么?占空间、浪费资源、访问速度慢、安全性低需要补充……通常选择阿里云、腾讯云、七牛云等对象存储OSS功能。通常每个平台都会提供自己的SDK,并配套各种示例,方便省心。不适合我们学习。举个简单的例子varOSS=require('ali-oss')//创建客户端varclient=newOSS({region:'',accessKeyId:'',accessKeySecret:'',bucket:''})constuploadSDK=async(obj)=>{varfileName=obj.files.file.namevarlocalFile=obj.files.file.pathtry{varresult=awaitclient.put(fileName,localFile)console.log(result.url)}catch(e){console.log(e)}returnresult.url}koa中展示的其他函数实现图片上传fs-文件系统路径-path单文件上传varfs=require('fs')varpath=require('path')constuploadStatic=async(obj)=>{//上传单个文件constfile=obj.files.file//创建一个可读流constreader=fs.createReadStream(file.path);letfilePath=path.join(__dirname,'../static/upload/')+`/${file.name}`;//创建一个可写流constupStream=fs.createWriteStream(filePath);//可读流通过管道写入可写流reader.pipe(upStream);return"上传成功!";}多文件上传varfs=require('fs')varpath=require('path')constuploadStatics=async(obj)=>{//上传多个文件constfiles=obj.文件.filefor(letfileoffiles){//创建一个可读流constreader=fs.createReadStream(file.path);让filePath=path.join(__dirname,'../static/upload/')+`/${file.name}`;//创建可写流constupStream=fs.createWriteStream(filePath);//可读流通过管道写入可写流reader.pipe(upStream);}return"上传成功!";}扩展大文件上传和上传进度获取涉及到大文件上传,我们不能用上面的方法,为什么?由于上传大文件通常需要很长时间,刷新/网速不佳等操作很容易导致文件上传失败,那么如何避免呢?分片和并发结合,将一个大文件分成多个块并发上传,大大提高了大文件的上传速度。当网络问题导致传输错误时,只需要重传错误的片段,而不需要重传整个文件。另外,分片传输可以实时跟踪上传进度。以vue项目为例,封装基于webuploader的Vue组件webuploader:一个以H5为主,FLASH为辅的简单现代文件上传组件分片的原理和过程当我们上传一个大文件的时候,会被插件分片,而且会有多个ajax,每个上传请求都是一个分片请求。将大文件分成多个小部分,一次一个地向服务器发送碎片。上传完成后,需要向服务器发送合并请求,让服务器合并多个分片文件。一个文件的原理:第一步:先对文件进行MD5加密,有两个好处,一是可以唯一标识文件,二是为即时传输做准备,二是在后台比较文件的完整性。:得到MD5值后,需要检查文件是否已经上传。如果已经上传过,则不需要再次上传,即可以秒传,网盘即时传的原理是一样的。第三步:对文件进行分片,如果文件是500M,我们定义一个分片大小为50M,那么将整个文件分成100次上传第四步:向后台请求一个接口,接口中的数据为文件为什么会出现这样的请求已经上传的文件块?我们经常使用网盘,网盘有断点续传的功能。当一个文件上传到一半的时候,由于各种原因,我不想再上传了,所以在再次上传的时候,服务器要保留我之前上传过的文件块,跳过这些上传的块,重新上传其他的文件块.当然,重新上传的方案有很多种。目前,单独发送请求效率最高。第5步:开始POST上传未上传的块。第六步:上传成功后,通知服务器合并文件。至此,上传完成!我们看一下upload发送的具体参数:第一个配置(content-disposition)和第二个配置中的access_token是webuploader配置中的formData,即传给服务器的参数接下来几个配置是文件内容,id,名称,类型,大小等,其中chunks是分片总数,chunk是图片当前分片个数,分别为12和分别为9个。当您看到带有chunk11的上传请求时,这意味着这是最后一个上传请求。