需求为:h5页面中,能够上传文件,不仅仅是图片。整体框架用的是uni-app,导致限制很多,尝试了很多方法,最后终于实现了。动态创建input标签,使用xhr上传,代码如下:
注意:请确认应用manifest.json文件的"permissions"字段中包括以下节点:
"h5" : {
"router" : {
"mode" : "hash",
"base" : ""
},
"title" : "",
"domain" : "域名",
"devServer" : {
"https" : false
},
"XMLHttpRequest": {
"description": "跨域网络访问"
}
}
1、需要上传的todo.vue页面中
<view class="addBox" ref="input">
<view class="upload">
<image src="../../static/upload.png"></image>
</view>
<view class="uploadtitle">上传简历</view>
</view>
2、在mounted中,开始创建input标签,methods里上传后台方法
mounted() {
this.$nextTick(function(){
var input = document.createElement('input')
input.style.width="100%";
input.type = 'file'//添加file类型
input.multiple = 'multiple'// 可以选择多个
// input.accept=".pdf" // 限制只能上传PDF文件,可以不限制,能上传任何类型
input.style.height="100%";
input.style.position="absolute";
input.style.top="0";
input.style.right="0";
input.style.opacity="0";
input.style.overflow="hidden"; //防止注意input 元素溢出
input.id = 'file';
var _this = this;
setTimeout(() => {
this.$refs.input.$el.appendChild(input); // 这里可能会报$el找不到错误,所以加了延时器,报错的原因是this.$refs.input没有找到为null,所以需要等页面结构加载完后再将其添加进去
input.onchange = (event) => { // 点击上传选择文件
var file = event.target.files;
if (file.length > 0) {
file.forEach(item => { // 因为后台限制,只能一个一个文件的上传,所以当选择多个文件后,需要遍历一个一个调用上传接口
_this.uploadAPI(item); // 上传图片
})
}
}
}, 1000)
})
},
methods: {
uploadAPI(path){
uni.showLoading({
title: '上传中'
})
var _this=this
var fData = new FormData();
fData.append("file",path);
fData.append("moduleName",'reports');
var xhr = new XMLHttpRequest();
var surl = '上传文件服务端URL';
xhr.open("POST",surl,true);
xhr.onload = function(e) {
// console.log("上传成功",e); //上传成功
let response = JSON.parse(e.currentTarget.response)
let file = response.data.url; //获取服务端传过来的文件地址
};
xhr.onreadystatechange = () =>{
if(xhr.readyState == 4 && xhr.status == 200){ //上传后台成功
uni.hideLoading()
var res =JSON.parse(xhr.responseText)
_this.fileList.push(res.datas); // 上传成功后放进fileList数组用于展示
} else {
uni.hideLoading()
}
}
// 这里设置请求头,做的时候遇到一个问题,明明上传的是FormData,可是在请求中变成了request payload,后台需要的是FormData,解决方法,设置enctype为multipart/form-data,不要设置Content-Type,切记直接不设置Content-Type
xhr.setRequestHeader('enctype',"multipart/form-data");
xhr.send(fData)
},
}
2、css样式
.addBox{
width: 100%;
height: 100px;
text-align: center;
position: relative;
border: 1px dashed #379479;
margin: 0 auto;
border-radius: 8px;
background-color: #FAFAFA;
}
.upload {
padding-top: 30rpx;
}
.upload > image {
width: 100rpx;
height: 100rpx;
}
.uploadtitle{
position: absolute;
bottom: 12rpx;
left: 0;
right: 0;
}
.filesBox{
margin-top: 28rpx;
}
.fileslist{
margin-top: 8px;
}
.upfileico{
width: 52rpx;
height: 52rpx;
display: inline-block;
vertical-align: top;
}
.upname{
font-size: 26rpx;
color: #333333;
width: 80%;
display: inline-block;
}
.upclose{
width: 40rpx;
height: 40rpx;
display: inline-block;
float: right;
position: relative;
top: 3px;
}