这是《大胖小课》栏目的专题一《说说文件上传那些事儿》的第二节-《写一个文件上传接口》
上一节 《大胖 • 小课》- 我是这样理解文件上传原理的,我们说到了文件上传的原理,服务端的文件保存我们使用koa-body来完成。
上传接口实现过程
在项目开发中,文件上传本身和业务无关,代码基本上都可通用。
服务端文件的保存基于现有的库koa-body
结合 koa2
实现服务端文件的保存和数据的返回。
koa-body
会自动保存文件到系统临时目录下os.tmpdir()
,也可以指定保存的文件路径。
然后在后续中间件内得到已保存的文件的信息,再做二次处理。
ctx.request.files.f1
得到文件信息,f1
为input file
标签的name
- 获得文件的扩展名,重命名文件
接口定义
接口地址:http://localhost:8100/upfile
接口返回格式
{ code:0, msg:'', data:'图片可访问地址' }
代码实现参考
NODE
/** * 服务入口 */ var http = require('http'); var koaStatic = require('koa-static'); var path = require('path'); var koaBody = require('koa-body');//解析 form-data消息体 var fs = require('fs');//文件模块 var Koa = require('koa2'); var app = new Koa(); var port = process.env.PORT || '8100';//默认端口8100 var uploadHost = `http://localhost:${port}/uploads/`;//图片可访问地址 app.use(koaBody({ formidable: { //设置文件的默认保存目录,不设置则保存在系统临时目录下 os uploadDir: path.resolve(__dirname, '../static/uploads') }, multipart: true // 支持文件上传,默认不不支持 })); //开启静态文件访问 app.use(koaStatic( path.resolve(__dirname, '../static') )); //二次处理文件,修改名称 app.use((ctx) => { if (ctx.path === '/upfile') { var file = ctx.request.files ? ctx.request.files.f1 : null; //得到文件对象 if (file) { var path = file.path.replace(/\\/g, '/'); var fname = file.name; //原文件名称 var nextPath = ''; if (file.size > 0 && path) { //得到扩展名 var extArr = fname.split('.'); var ext = extArr[extArr.length - 1]; nextPath = path + '.' + ext; //重命名文件 fs.renameSync(path, nextPath); } //以 json 形式输出上传文件地址 ctx.body = getRenderData({ data: `${uploadHost}${nextPath.slice(nextPath.lastIndexOf('/') + 1)}` }); }else { ctx.body = getRenderData({ code:1, msg:'file is null' }); } } }); /** * * @param {设置返回结果} opt */ function getRenderData(opt) { return Object.assign({ code:0, msg:'', data:null },opt); } /** * http server */ var server = http.createServer(app.callback()); server.listen(port); console.log('upload file server start ...... ');
接口测试
//启动服务 $ node ./src/upfiles-demo/api-upfile/server/app.js //访问静态 html 页面 http://localhost:8100/html/upfile.html //选择文件后上传