需求为:h5页面中,能够上传文件,不仅仅是图片。整体框架用的是uni-app,导致限制很多,尝试了很多方法,最后终于实现了。动态创建input标签,使用xhr上传,代码如下:
1,需要上传的todo.vue页面中,
<view class="flex flex-align-center flex-pack-justify" >
// 动态创建input标签
<view class="addBox" ref="input">
<view class="uploadtitle">点击上传文件</view>
</view>
// 上传的文件列表展示
<view class="filesBox" v-if="fileList.length > 0">
<view class="fileslist" v-for="item in fileList">
<image src="/static/images/upfile.png" class="upfileico"></image>
<text class="upname">{{item.fileOriginalName}}</text>
<image src="/static/images/upclose.png" class="upclose" @click="delUpFile(item)"></image>
</view>
</view>
</view>
2,css样式
.addBox{
width: 100%;
height: 100px;
text-align: center;
background: url(/static/images/upload.png) no-repeat center center;
position: relative;
border: 1px dashed #1890FF;
margin: 0 auto;
border-radius: 8px;
background-color: #FAFAFA;
}
.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;
}
3,在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 = util.commonUrl() + api.uploadUrl;
xhr.open("POST",surl,true);
xhr.onload = function(e) {
// console.log("上传成功",e); //上传成功
};
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.setRequestHeader('Authorization',util.getToken());
xhr.send(fData)
},
/**
* 列表删除文件
*
*/
delUpFile(data){
this.fileList = this.fileList.filter(item => item.id !== data.id)
}
}
4,结果图