让我来详细讲解一下“vue+element+oss实现前端分片上传和断点续传”的完整攻略。
前置知识
在开始之前,我们需要确保您已经掌握以下技能:
- vue.js框架
- element-ui组件库
- Javascript
- 阿里云OSS
准备工作
在开始项目之前,您需要准备以下工具:
- npm包管理器
- vue-cli脚手架
项目搭建
首先,我们需要使用vue-cli创建一个新的vue项目,您可以在终端中运行以下代码:
vue create my-project
接着,安装element-ui依赖:
npm install element-ui -S
安装阿里云OSS依赖:
npm install ali-oss -S
分片上传实现
分片上传的原理是将一个大文件分割成多个小文件,然后逐一上传。以下是示例代码:
<template>
<div class="chunk-upload">
<el-upload :action="action" :before-upload="beforeUpload" :on-change="changeFileList">
<el-button size="small" type="primary">
点击上传文件
</el-button>
</el-upload>
</div>
</template>
<script>
import oss from 'ali-oss';
export default {
data() {
return {
action: 'your-upload-url', //上传接口
file: null,
sliceSize: 2 * 1024 * 1024, //切片大小
threadsNum: 4 //同时上传的切片数量
};
},
methods: {
async beforeUpload(file) {
this.file = file;
},
async changeFileList(fileList) {
if (fileList.length == 0) return;
const client = oss({
region: 'your-region', //OSS所在区域
accessKeyId: 'your-access-key-id',
accessKeySecret: 'your-access-key-secret',
bucket: 'your-bucket-name',
secure: true //如果是SSL连接,值为true
});
const fileName = this.file.name;
let sliceStart = 0;
const fileSize = this.file.size;
let chunks = [];
while (sliceStart < fileSize) {
const sliceEnd = Math.min(sliceStart + this.sliceSize, fileSize);
const slice = this.file.slice(sliceStart, sliceEnd);
chunks.push(slice);
sliceStart += this.sliceSize;
}
const headers = {
'x-oss-object-acl': 'public-read'
};
const uploadRes = await client.multipartUpload(fileName, chunks, {
headers,
partSize: this.sliceSize,
parallel: this.threadsNum
});
console.log(uploadRes);
}
}
};
</script>
<style>
.chunk-upload {
width: 80%;
margin: 40px auto;
padding: 24px;
border: 1px solid #eee;
border-radius: 4px;
}
</style>
在上面的代码中,您需要将action
替换成您的上传接口地址。执行UPLOAD的函数是changeFileList
, 它将文件分割成若干个切片,并将它们上传到OSS,最后使用multipartUpload函数将所有部分组合在一起。在multipartUpload函数中,您需要指定每个部分的大小和同时上传的部分数目。
断点续传实现
断点续传是指在上传大文件时,可以在中途停止上传,然后从上次停止的位置继续上传。以下是示例代码:
<template>
<div class="resume-upload">
<el-upload :action="action" :before-upload="beforeUpload" :on-progress="onProgress" :on-success="onSuccess">
<el-button size="small" type="primary">
点击上传文件
</el-button>
</el-upload>
<el-progress :percentage="progress" :color="progressColor" :stroke-width="10" :text-inside="true" />
</div>
</template>
<script>
import OSS from 'ali-oss';
export default {
data() {
return {
action: 'your-upload-url',
file: null,
client: null,
progress: 0,
lastLoaded: 0,
chunkSize: 2 * 1024 * 1024, //切片大小
progressColor: '#66CCFF' //进度条颜色
};
},
methods: {
async beforeUpload(file) {
this.file = file;
//初始化OSS客户端
this.client = new OSS({
region: 'your-region',
accessKeyId: 'your-access-key-id',
accessKeySecret: 'your-access-key-secret',
bucket: 'your-bucket-name',
secure: true
});
},
async uploadPart(uploadId, index, chunk) {
const result = await this.client.uploadPart(this.file.name, uploadId, index, chunk, {
progress: async (p) => {
p = p * 100 >> 0;
if (p > this.progress) {
this.progress = p;
}
},
meta: {
'x-oss-object-acl': 'public-read'
}
});
return result;
},
async createUploadId() {
const res = await this.client.initiateMultipartUpload(this.file.name, {
meta: {
'x-oss-object-acl': 'public-read'
}
});
return res.uploadId;
},
async completeUpload(uploadId, etags) {
const res = await this.client.completeMultipartUpload(this.file.name, uploadId, etags, {
meta: {
'x-oss-object-acl': 'public-read'
}
});
return res;
},
async upload() {
const fileSize = this.file.size;
const chunkCount = Math.ceil(fileSize / this.chunkSize);
let uploadId;
let etags = new Array(chunkCount);
const fileName = this.file.name;
try {
uploadId = await this.createUploadId();
for (let i = 0; i < chunkCount; i++) {
const start = i * this.chunkSize;
const end = Math.min(start + this.chunkSize, fileSize);
const chunk = this.file.slice(start, end);
const result = await this.uploadPart(uploadId, i + 1, chunk);
etags[i] = {
PartNumber: i + 1,
ETag: result.res.headers.etag
};
this.lastLoaded = end;
}
await this.completeUpload(uploadId, etags);
console.log('断点续传成功');
} catch (err) {
console.log(err);
}
},
async onProgress(event) {
const loaded = event.loaded + this.lastLoaded;
const total = this.file.size;
if (total > 0) {
this.progress = (loaded / total * 100) >> 0;
}
},
async onSuccess() {
await this.upload();
}
}
};
</script>
<style>
.resume-upload {
width: 80%;
margin: 40px auto;
padding: 24px;
border: 1px solid #eee;
border-radius: 4px;
}
</style>
在上面的代码中,您需要将action
替换为您的上传接口地址。断点续传函数是upload
。在该函数中,我们将文件切成若干部分,并将它们逐一上传,记录上传队列的ETags。如果有任何一个部分上传失败,使用该函数的catch语句回滚操作。参考以上代码,加入自己的项目中可完成前端分片上传和断点续传。
这就是“vue+element+oss实现前端分片上传和断点续传”的完整攻略。希望本文能对您有所帮助。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:vue+element+oss实现前端分片上传和断点续传 - Python技术站