1.如果"ali-oss"版本为6.0以上,那么我们在使用multipartUpload分片上传会遇到很多坑。
比如:上传的文件只能小于100kb,否则上传失败,此时我们要对OSS添加useFetch: true
可以完美解决,如下是我的配置
export function client(data) {
//后端提供数据
return new OSS({
region: "oss-cn-hangzhou",
accessKeyId: data.accessKeyId,
accessKeySecret: data.accessKeySecret,
useFetch: true, //支持上传大于100KB的文件
secure: true, //使用https上传
bucket: "resdev",
stsToken: data.stsToken,
refreshSTSToken: async () => {
const info = await this.$api.getUploadConfig();
return {
accessKeyId: info.data.accessKeyId,
accessKeySecret: info.data.accessKeySecret,
stsToken: info.data.stsToken,
};
},
refreshSTSTokenInterval: 300000,
});
}
如下是完整的代码,上传文件组件.我用的是vant框架
<template>
<div>
<van-uploader
v-model="fileList"
:before-read="beforeUpload"//上传前调用的方法
:after-read="Upload"//上传后调用的方法
:before-delete="beforeDelete"//删除之前调用的方法
@delete="deleteHandler"//删除图片时调用的方法
accept="image/*,.doc,.docx,.pdf,.ppt" //可以接受的图片格式
:max-size="100 * 1024 * 1024"//限制图片大小
:max-count="fileCount"//最大上传数量,从父组件传递
multiple//支持多文件上传
/>
</div>
</template>
<script>
const OSS = require("ali-oss");
const uuid = require("uuid");
export function client(data) {
//后端提供数据
return new OSS({
region: "oss-cn-hangzhou",
accessKeyId: data.accessKeyId,
accessKeySecret: data.accessKeySecret,
useFetch: false, //android上传大于100M
secure: true, //使用https
bucket: "resdev",
stsToken: data.stsToken,
refreshSTSToken: async () => {
const info = await this.$api.getUploadConfig();
return {
accessKeyId: info.data.accessKeyId,
accessKeySecret: info.data.accessKeySecret,
stsToken: info.data.stsToken,
};
},
refreshSTSTokenInterval: 300000,
});
}
export default {
props: ["imgUrl", "imageMax", "urlPath", "listType", "tag", "fileCount"],
data() {
return {
loading: false,
imageUrl: [],
dataObj: {}, //存签名信息
baseAli: "oss-cn-hangzhou.aliyuncs.com", //后面连接图片url用的,根据自己aili OSS 配制修改
previewVisible: false,
previewImage: "",
isvideo: 0,
deleteList: [], //删除的图片,再提交时删除
client: function () {},
tempCheckpoint: "",
delImgUrl: [],
upImgUrl: [],
fileList: [],
fileListUpload: [],
};
},
mounted() {},
methods: {
//上传前配置
async beforeUpload(file) {
return new Promise((resolve, reject) => {
let arr = [];
if (!file[0]) {
arr.push(file);
} else {
arr = file;
}
for (let i = 0; i < arr.length; i++) {
let maxSize = 20;
const isLimitSize = arr[i].size / 1024 / 1024 < maxSize;
if (!isLimitSize) {
this.$toast("文件不能超过" + maxSize + "MB!");
reject();
}
}
this.$api
.getUploadConfig()
.then((response) => {
this.dataObj = response.data;
resolve();
})
.catch((err) => {
this.$dd.device.notification.alert({
message: err,
buttonName: "确定",
});
reject();
});
});
},
//上传
async Upload(file) {
const that = this;
let arr = [];
if (!file[0]) {
arr.push(file);
} else {
arr = file;
}
for (let i = 0; i < arr.length; i++) {
arr[i].status = "uploading";
arr[i].message = "上传中...";
let filetype = arr[i].file.type.substring(
arr[i].file.type.indexOf("/") + 1
);
const fileName = that.urlPath + uuid.v4() + "." + filetype;
await client(that.dataObj)
.multipartUpload(fileName, arr[i].file})
.then((result) => {
alert("成功");
if (result.res.status == 200) {
arr[i].status = "success";
arr[i].message = "上传成功";
let fileurlArr = result.res.requestUrls[0].split("?");
let fileInfo = {
tag: that.tag, //文件标签名称
fileName: result.name.substring(result.name.indexOf("/") + 1), //文件名称
sourceName: arr[i].file.name, //原始文件名称
filePath: fileurlArr[0], //文件路径
contentType: arr[i].file.type.substring(
arr[i].file.type.indexOf("/") + 1
), //文件类型
size: arr[i].file.size.toString(), //文件大小
};
return fileInfo;
} else {
arr[i].status = "failed";
arr[i].message = "上传失败";
}
})
.then((res) => {
that.$api
.uploadFile(res)
.then((resdata) => {
let url = {
ids: resdata.data.id,
name: resdata.data.fileName,
filename: resdata.data.sourceName,
};
that.upImgUrl.push(url);
that.fileListUpload.push(url);
that.$emit("finishUpload", that.fileListUpload);
})
.catch((err) => {
this.$dd.device.notification.alert({
message: err,
buttonName: "确定",
});
});
})
.catch((err) => {
alert(err);
alert("失败");
arr[i].status = "failed";
arr[i].message = "上传失败";
});
}
},
//删除前
async beforeDelete(file) {
let that = this;
that.delImgUrl = [];
let fileName = file.file.name;
return await new Promise((resolve, reject) => {
that
.$confirm({ message: "是否确认删除当前图片", title: "删除提示" })
.then(() => {
this.$api
.getUploadConfig()
.then((response) => {
this.dataObj = response.data;
let delimg = that.upImgUrl.filter((item) => {
return item.filename == fileName;
});
delimg[0].filepathname = "restms/" + delimg[0].name;
that.delImgUrl.push(delimg[0]);
resolve();
})
.catch((err) => {
reject();
this.$dd.device.notification.alert({
message: err,
buttonName: "确定",
});
});
})
.catch((err) => {
this.$dd.device.notification.alert({
message: err,
buttonName: "确定",
});
reject();
});
});
},
async deleteHandler() {
const that = this;
let delfile = await that.delImgUrl.map((item) => {
return item.filepathname;
});
try {
let result = await client(that.dataObj).deleteMulti(delfile);
if (result.res.status == 200) {
let imgid = that.delImgUrl[0].ids;
that.$api
.delUploadFile({ ids: that.delImgUrl[0].ids })
.then((res) => {
if (res.data.count == 1) {
let del_index;
for (let i = 0; i < that.fileListUpload.length; i++) {
if (imgid == that.fileListUpload[i].ids) {
del_index = i;
}
}
that.fileListUpload.splice(that.fileListUpload[del_index], 1);
that.$emit("finishUpload", that.fileListUpload);
that.$toast("删除成功!");
} else {
that.$toast("图片不存在!");
}
})
.catch((err) => {
console.log(err, "err");
});
}
} catch (e) {
this.$toast("删除失败!");
console.log(e, "删除失败");
}
},
},
watch: {
imgUrl: {
handler(val) {
if (val) {
this.$set(this, "fileList", val);
}
},
immediate: true,
},
},
};
</script>
在父组件中调用:
<template>
<div>
<upload-file urlPath="restms/" tag="ACN-contract" fileCount="6" @finishUpload="getImgList"></upload-file>
</div>
</template>
<script>
import uploadFile from "@/components/upload.vue";
export default {
name: "uploadimg",
components: {"upload-file": uploadFile,"upload-file1": uploadFileF},
data() {
return {};
},
methods:{
getImgList(x){
console.log("父组件获取列表",x)
},
}
};
</script>
注:
我做的项目在钉钉微应用,现在有个大坑是在钉钉IOS端,无法上传文件,IOS中的浏览器是可以上传的,但是钉钉微应用里面就是不行,安卓可以完美实现上传,经过两日苦战,发现IOS不支持multipartUpload,此时我把multipartUpload改为put方法,完美解决!