<template>
<div>
<el-upload class="avatar-uploader" action :show-file-list="false" :http-request="handleUpload" :disabled="disabled || loading">
<slot>
<el-button :disabled="disabled" type="primary" :loading="loading">
<slot name="text">上传APK</slot>
</el-button>
</slot>
</el-upload>
<el-progress v-if="loading" class="mt10" :text-inside="true" :stroke-width="20" :percentage="percentage" />
<div v-if="parsing" style="color:#f56c6c">上传完成,正在解析,请稍后...</div>
</div>
</template>
<script>
import ObsClient from "esdk-obs-browserjs/src/obs";
import request from "@/config/serve.js"; // 导入已经封装的请求方法 这里根据你自己的请求方法来修改和使用
export default {
props: {
expandData: {}, // 其他附加数据
// 是否禁用
disabled: {
type: Boolean,
default: false,
},
},
data() {
return {
url: "",
initiateData: {
option: {},
uploadId: "",
},
fileName: "",//上传的文件名
fileUrl: "",//上传到华为云的文件路径
obsClient: null,
loading: false,// 整个上传是否完成
parsing: false,// 上传完成,正在解析包体
Bucket: "yourBucket",// 桶名
obsUrl: "yourObsUrl",//拼接地址
percentage: 0,//文件上传进度
fileSize: "",// 文件大小
};
},
methods: {
async handleUpload(option) {
const isUpload = await this.beforeUpload(option.file);
if (!isUpload) return;
await this.getObsClient();
this.loading = true;
const _this = this;
this.initiateData.option = option;
let _fileName = option.file.name; // 文件名
const fileSuffixIndex = _fileName.lastIndexOf("."); // 找到文件后缀名的位置
_fileName = `${_fileName.substring(0, fileSuffixIndex)}_${new Date().getTime()}${_fileName.substring(fileSuffixIndex)}`; // 添加时间戳
this.fileName = _fileName;
this.fileUrl = "market/apk/" + _fileName; // 路径 + 文件名 market/apk为案例 根据你的实际情况而定
const params = {
Bucket: this.Bucket, // 桶名
Key: this.fileUrl,
};
this.obsClient.initiateMultipartUpload(params).then((result) => {
if (result.CommonMsg.Status < 300) {
const uploadId = result.InterfaceResult.UploadId;
_this.initiateData.uploadId = uploadId;
/*
* Step 2: upload a part
*/
const etag = [];
const uploadPromise = new Promise((resolve) => {
this.fileSize = option.file.size;
const partLen = 200 * 1024 * 1024;// 分片大小
const count = Math.ceil(option.file.size / partLen);
const indexNum = 0;
this.uploadPartMethod(option, uploadId, indexNum, partLen, etag, count, resolve);
});
uploadPromise.then((result) => {
const paramsEnd = {
Bucket: this.Bucket,
Key: this.fileUrl,
UploadId: uploadId,
Parts: etag.sort((a, b) => a.PartNumber - b.PartNumber),
};
this.obsClient.completeMultipartUpload(paramsEnd).then((result) => {
if (result.CommonMsg.Status < 300) {
const url = this.obsUrl + this.fileUrl; //返回访问链接
this.url = url;
const obj = {
accessPath: url,
fileName: this.fileName,
suffix: "apk",
};
this.getApkInfo(obj);
}
});
});
}
});
},
async beforeUpload(file) {
let isFileType = true
const fileName= file.name;
const fileType = fileName.substring(fileName.lastIndexOf(".") + 1).toLowerCase();
isFileType = ["apk"].includes(fileType);
if (!isFileType) {
this.$message.error(`上传文件只能是 apk 格式!`);
}
// 文件名只含有大小写字母、数字、下划线、-、中文.
var regex=/^[A-Za-z0-9_\-\.\u4e00-\u9fa5]+$/ig;
const isLegalName = regex.test(fileName);
if(!isLegalName){
this.$message.error("上传的文件只能由大小字母、数字、下划线、中文组成");
}
return isFileType && isLegalName;
},
uploadPartMethod(option, uploadId, indexNum, partLen, etag, count, resolve) {
const _this = this;
console.log('正在上传分片', indexNum + 1, count);
this.obsClient.uploadPart({
Bucket: this.Bucket,
Key: this.fileUrl,
UploadId: uploadId,
PartNumber: indexNum + 1,
SourceFile: option.file,
PartSize: partLen,
Offset: partLen * indexNum,
ProgressCallback: function (transferredAmount, totalAmount, totalSeconds) {
// 获取上传平均速率(KB/S)
// console.log(transferredAmount * 1.0 / totalSeconds / 1024);
// 已上传的文件大小
const preSize = partLen * indexNum + transferredAmount
// 获取上传进度百分比
_this.percentage = Math.ceil(preSize * 100 / _this.fileSize)
}
}).then((result) => {
etag.push({
ETag: result.InterfaceResult.ETag,
PartNumber: indexNum + 1,
});
indexNum++;
if (indexNum < count) {
_this.percentage = Math.ceil((indexNum / count) * 100);
option.file.percent = _this.percentage;
option.onProgress(option.file);
_this.uploadPartMethod(option, uploadId, indexNum, partLen, etag, count, resolve);
}
if (indexNum == count) {
_this.percentage = 100;
option.file.percent = _this.percentage;
option.onProgress(option.file);
resolve("任务完成");
this.percentage = 100
}
});
},
async getObsClient() {
const res = await request("请求方法", "你的接口地址", {}, false);
const hwSecret = res.data.credential;
this.obsClient = new ObsClient({
access_key_id: hwSecret.access,
secret_access_key: hwSecret.secret,
security_token: hwSecret.securitytoken,
server: "yourServer",
});
},
// 获取上传apk信息
async getApkInfo(params) {
this.parsing = true;
try {
const res = await request("请求方法", "你的接口地址", params, false);
if (res && res.code === 0) {
const data = res.data;
this.$emit("success", data);// 上传成功,返回数据
}
this.loading = false;
this.parsing = false;
this.percentage = 0
} catch (err) {
this.loading = false;
this.parsing = false;
this.percentage = 0
}
},
// 暴露给父组件校验组件文件是否正在上传
getValidate(showMsg = true) {
if (this.loading) {
if (showMsg) {
this.$message.error("文件正在上传,请稍后;");
}
return false;
}
return true;
},
},
};
</script>
05-12
850
04-20
421
02-23
6287
12-31