最近在丰富Enlarge上传文件到手机上,因为项目中ajax是用了axios,所以文件上传也准备用它来做,以下是上传文件示例,网上也有很多代码:
// input的onchange事件
onFileSelected(e) {
var data = new FormData();
for (let i = 0; i < e.target.files.length; i++) {
data.append(e.target.files[i].name, e.target.files[i]);
}
data.append("dir", this.currentPath);
let instance = axios.create({
// 设置header
headers: { 'Content-Type': 'charset=UTF-8; multipart/form-data;' }
});
var that = this;
instance.post(this.custom_config.http_server + this.custom_config.api.fileManager.upload, data)
.then(function(data){
if (data.data.code == 200) {
//refresh
that.onRefreshClick();
}
},function(err){
//eslint-disable-next-line
console.log(err);
})
//把input的value置空,否则选择了文件之后再点会不能弹选择文件对话框,原因是value没有变化
this.$refs.upload.value = null;
}
按上面的代码在server端一开始能收到post请求,但是要的文件参数没有,因为server是用nanohttpd,后面找到原因是post请求时要主动再调一下parseBody:
HashMap<String, String> map = new HashMap<>();
try {
session.parseBody(map);
} catch (Exception e) {
}
这个参数能收到了,但是文件名是中文时乱码!想到是不是上传的时候编码不对,但不是主动设置了content-type包含了charset=UTF-8了吗,通过devtools看到,其实content-type里并没有chartset=UTF-8!实际是这样的:
Content-Type: multipart/form-data; boundary=----WebKitFormBoundarybEhkqA1knJQPIdvf
后面用了各种axios的方法都不行,最终知道原来这是个axios的bug一直没有修复。。。于是继续找别的办法,axios不行,那我用原生fetch可以了吧,结果是设置了content-type不能走正常post上传(因为multi-part要有boundary),不设置的话可以上传,但一样有编码问题!这也不行,那用form上传可以吗,试了,也是一样的!为啥设置个charet就这么难呢,于是在服务端进行解决,因为没有charset的时候默认是用ascii编码的,于是改了下multi-part时的content-type如果没有charset默认就用utf-8的编码来解析, 于是终于大功告成,其实还有一种解决方法是在服务端获取参数时把编码再从ascii转回utf-8来,这个没试。如果不在服务端解决,客户端是各写上传逻辑加上charset或许也是种解决办法,暂没去研究!
完整代码请看github:Enlarge-Web和Enlarge-Android