在平常开发过程当中,有不少需求涉及到图片/文件上传,那么用Koa如何实现?
以前的课程讲过,Koa框架是一个基于中间件的框架,咱们所须要的一些功能都须要安装相对应的中间件库。
而要实现文件上传,有不少插件:vue
这里推荐使用koa-body!咱们来仔细研究一下它!web
以前使用 koa2 的时候,处理 post 请求使用的是 koa-bodyparser,同时若是是图片上传使用的是 koa-multer。
这二者的组合没什么问题,不过 koa-multer 和 koa-route(注意不是 koa-router) 存在不兼容的问题。ajax
koa-body结合了两者,因此koa-body能够对其进行代替。npm
在 koa2 中使用 koa-body,我使用的是全局引入,而不是路由级别的引入,由于考虑到不少地方都有 post 请求或者是文件上传请求,不必只在路由级别引入。安全
npm i koa-body -D
const koaBody = require('koa-body'); const app = new koa(); app.use(koaBody({ multipart:true, // 支持文件上传 encoding:'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); console.log(ctx.request.body); ctx.body = JSON.stringify(ctx.request.files); });
为何起这个标题呢,由于如今不少企业级的项目都不会选择将一些图片文件存储在本身的服务器中,为何?网络
一般都会选择阿里云,腾讯云,七牛云等对象存储OSS功能。并发
一般每一个平台都会提供本身的SDK,并配套各类示例,方便省心。不适合咱们学习。app
举个简单的例子框架
var OSS = require('ali-oss') // 建立客户端 var client = new OSS({ region: '', accessKeyId: '', accessKeySecret: '', bucket: '' }) const uploadSDK = async (obj) => { var fileName = obj.files.file.name var localFile = obj.files.file.path try { var result = await client.put(fileName, localFile) console.log(result.url) } catch (e) { console.log(e) } return result.url }
其余功能如图
var fs = require('fs') var path = require('path') const uploadStatic = async (obj) => { // 上传单个文件 const file = obj.files.file // 建立可读流 const reader = fs.createReadStream(file.path); let filePath = path.join(__dirname, '../static/upload/') + `/${file.name}`; // 建立可写流 const upStream = fs.createWriteStream(filePath); // 可读流经过管道写入可写流 reader.pipe(upStream); return "上传成功!"; }
var fs = require('fs') var path = require('path') const uploadStatics = async (obj) => { // 上传多个个文件 const files = obj.files.file for (let file of files) { // 建立可读流 const reader = fs.createReadStream(file.path); let filePath = path.join(__dirname, '../static/upload/') + `/${file.name}`; // 建立可写流 const upStream = fs.createWriteStream(filePath); // 可读流经过管道写入可写流 reader.pipe(upStream); } return "上传成功!"; }
涉及到大文件上传,咱们就不能采用上面的方法,为何?由于一般大文件上传耗时很长,刷新/网速差等操做很容易致使文件上传失败,那么如何去避免?
分片与并发结合,将一个大文件分割成多块,并发上传,极大地提升大文件的上传速度。
当网络问题致使传输错误时,只须要重传出错分片,而不是整个文件。另外分片传输可以更加实时的跟踪上传进度。
以vue项目为例
webuploader: 一个简单的以H5为主,FLASH为辅的现代文件上传组件
<vue-upload ref="uploader" url="xxxxxx" uploadButton="#filePicker" multiple @fileChange="fileChange" @progress="onProgress" @success="onSuccess" ></vue-upload>
当咱们上传大文件时,会被插件进行分片,ajax会有多个
原理:
咱们来看看upload发送的具体参数:
第一个配置(content-disposition)中的guid和第二个配置中的access_token,是咱们经过webuploader配置里的formData,即传递给服务器的参数 后面几个配置是文件内容,id、name、type、size等 其中chunks为总分片数,chunk为当前第几个分片。图片中分别为12和9。当你看到chunk是11的upload请求时,表明这是最后一个upload请求了。