koa-body是一款为实现文件上传的中间件。
本文主要就利用该插件实现上传时遇到的问题进行些整理。
1 ctx.request.files.file ---------->终端提示undefined问题.
主要原因在于koa-body版本问题。koa-body v3和v4之前通过ctx.request.body捕获文件。而v3.v4终才是通过ctx.request.files.file进行获取。所以在安装过程中要指定版本。
正解:
cnpm install koa-body@4
默认cnpm install koa-body安装依然是v3之前的版本
2 关于中间件顺序问题。
在路由中间件和koa-body都存在的情况下,务必让koa-body在koa-router之前。否则会报错。
demo结构
----node_moudules
----static //存放静态资源文件夹
form.html 表单html页面
-----test.js //服务器测试文件
代码展示:
---------------------------------test.js----------------------------------------
var koa=require("koa");
var fs=require("fs");
var path=require("path");
var router=require("koa-router")();
var static=require("koa-static");
var bodyParser=require("koa-bodyparser");
var koaBody=require("koa-body")
var fs=require("fs")
var app=new koa();
const uploadUrl="http://hocalhost:8989/static/upload";
//配置中间件,注意顺序
app.use(bodyParser());
app.use(koaBody({
multipart:true,
formidable:{
maxFieldsSize:10*1024*1024,
multipart:true
}
}))
app.use(router.routes())
app.use(router.allowedMethods())
app.use(static(__dirname+"/static"))
//配置路由
router.get("/",async(ctx)=>{
ctx.response.type = 'html'; //注意设置文件头很重要。如果不设置,打开首页会进入下载
ctx.response.body=fs.createReadStream(__dirname+'/static/form.html');
})
router.post("/upload", async (ctx)=>{
const file=ctx.request.files.file;
const reader=fs.createReadStream(file.path);
let filePath=__dirname+"/static/upload/";
let fileResource=filePath+`/${file.name}`;
if(!fs.existsSync(filePath)){ //判断staic/upload文件夹是否存在,如果不存在就新建一个
fs.mkdir(filePath,(err)=>{
if(err){
throw new Error(err)
}else{
let upstream=fs.createWriteStream(fileResource);
reader.pipe(upstream);
ctx.response.body={
url:uploadUrl+`/${file.name}`
}
}
})
}else{
let upstream=fs.createWriteStream(fileResource)
reader.pipe(upstream);
ctx.response.body={
url:uploadUrl+`/${file.name}` //返给前端一个url地址
}
}
})
app.listen(8989)
-----------------------------------------form.html---------------------------------------------------
前端代码://注意控件需要设置name属性
<form action="http://localhost:8989/upload" method="post" enctype="multipart/form-data" id="fm">
<p><input type="password" name="password" password=""/></p> -->
<p><input type="file" name="file" id="file"></p>
<p><input type="submit" value="提交"/></p>
</form>
前端也可以采用无刷新方式进行网络请求的方式。html结构只需要一个file文件域即可,但是我们需要通过axios或者fetch等方式进行网络请求
<body>
<input type="file" name="file" id="file">
</body>
<script>
var fileObj=document.getElementById("file");
fileObj.οnchange=function(e){
var file=e.target.files[0];
var fd=new FormData();
fd.append("file",file);
fetch("http://localhost:9999/upload",{
method:"POST",
body:fd,
// headers:{ //注意:这里无需设置headers属性。浏览器会自动设置
// "Content-Type": "multipart/form-data"
// },
}).then(res=>{
return res.json()
}).then(data=>{
console.log("data:",data)
}).catch(err=>{
console.log("err:",err)
})
}
</script>