Vue使用AWS s3进行大文件的分片上传、断点续传、下载(将文件上传进度显示)

如果想要单纯的不依赖后端的版本,可参考我这篇博客

将AWS S3大文件文件上传相关的API集成为js文件,功能包括 多文件并行上传、文件分片上传、断点续传、文件分片合成、上传暂停、取消上传、文件上传进度条显示_初八不乖的博客-CSDN博客

 效果

Vue使用AWS s3进行大文件的分片上传、断点续传、下载(将文件上传进度显示)_第1张图片

流程

AWS S3的官方文档(GetObject - Amazon Simple Storage Service)

 一、上传文件

 1. npm下载 aws-sdk

npm install @aws-sdk/client-s3

2.将aws-sdk集成到vue中

const {
    S3Client,
    CreateMultipartUploadCommand,
    ListMultipartUploadsCommand,
    GetObjectCommand,
    UploadPartCommand,
    CompleteMultipartUploadCommand,
    AbortMultipartUploadCommand
} = require("@aws-sdk/client-s3");
//这里显示的是后面要用到的s3中的方法,具体怎么使用,后面会讲到

3.向后端获上传文件所需要的信息

(存储文件的bucket,存储节点(endPoint也就是存储服务器的ip)、accessKey(访问用户名)、secretKey(访问密码))

这一步也可以直接在前端获取这些信息(如何获取这些信息请参照博客:minio使用案例(Springboot)_子午谷的博客-CSDN博客_minio代理)

我这里是已经创建了bucket了,如果没有创建bucket要先创建

创建方法:
注意:endpoint不要加端口,有默认端口(https,http协议端口不同),如果需要转换端口,可以考虑使用ngnix,如果在这里加了端口,会报错

var s3 = new S3Client({
     endpoint: "https://" + s3Information.endPoint,//存储文件的服务器的地址,无端口
     s3ForcePathStyle: true,
     signatureVersion: 'v4',
     region: 'us-east-1',
     forcePathStyle: true,
     credentials: {
           accessKeyId: "",//访问登录名
           secretAccessKey: "",//访问密码
       }
  });
 var params = {
     Bucket: "examplebucket"//bucket名,任意取
 };
 s3.CreateBucketCommand(params, function(err, data) {
   if (err) console.log(err, err.stack); // 错误
   else     console.log(data);           // 成功
 });

4.建立连接

在每一个文件上传时,都要先与服务器建立连接,并获取唯一的uploadId

//建立连接
//key标识文件的名称
//type为文件的类型
//s3为创建bucket时建立的S3Client
        async createMultipartUpload(bucket, key, s3, type) {// string, string
            const params = {
                Bucket: bucket,
                Key: key,
                ContentType: type
            };
            const res = async () => {
                try {
                    const data = await s3.send(new CreateMultipartUploadCommand(params));
                    return data;
                } catch (err) {
                    console.log('建立连接失败:', err.message)
                    return 1;
                }

            }
            return res()
        },

5.选择文件,并将文件切片,分段上传

注意:s3分片上传文件时,只有最后一个分片的文件可以小于5M,其余分片必须大于等于5M,否则会报错(Your proposed upload is smaller than the minimum allowed object size)

阶段所使用的主要方法和步骤

  • 文件分片
const chunkSize = 5 * 1024 * 1024;//定义分片的大小 为5M  采用分片上传时,只能并且只有有最后一个分片的size 小于 指定值(默认5M),不然就会报错
const chunkCount = Math.ceil(this.fileList[i].files.size / chunkSize)//分片数
for (let j = 0; j < chunkCount; j++) {
     let start = j * chunkSize;
     let end = Math.min(this.fileList[i].files.size, start + chunkSize)
     let _chunkFile = this.fileList[i].files.slice(start, end)//分片文件
}
  • 文件分片上传至bucket
//上传一个分片
//f为一个文件分片
//uploadId 为建立连接时返回的唯一id
///key为文件名
//num为第几个分片
//s3为S3Client
        async uploadPart(f, uploadId, key, bucket, num, s3) {
            const params = {
                Bucket: bucket,
                Key: key,
                PartNumber: num,
                UploadId: uploadId,
                Body: f
            };
            const res = async () => {
                try {
                    const data = await s3.send(new UploadPartCommand(params));
                    return data;
                } catch (err) {
                    // return alert("There was an error listing your albums: " + err.message);
                    console.log('上传分片错误信息', err.message)
                    return 1;
                }

            }
            return res();
        },

6.文件分片均上传成功后,要对分片进行合并

注意:在分片上传完成,并且合并之后,系统会自动断开连接;如果是发异常,如上传分片失败等,需要手动断开连接

//将分片合并
//parts是一个数组,形式为{ ETag: 分片上传成功后返回的唯一标识, PartNumber: 第几个分片 }
        async completeMultipartUpload(bucket, key, parts, uploadId, s3) {
            const params = {
                Bucket: bucket,
                Key: key,
                MultipartUpload: {
                    Parts: parts
                },
                UploadId: uploadId
            };
            const res = async () => {
                try {
                    const data = await s3.send(new CompleteMultipartUploadCommand(params));
                    return data
                } catch (err) {
                    console.log("合并分片失败: ", err.message);
                    return 1
                }

            }
            return res()
        },
//取消连接
        async abortMultipartUpload(bucket, key, uploadId, s3) {
            const params = {
                Bucket: bucket,
                Key: key,
                UploadId: uploadId
            };
            const res = async () => {
                try {
                    const data = await s3.send(new AbortMultipartUploadCommand(params));
                    return data
                } catch (err) {
                    console.log("取消连接失败: " + err.message);
                    return 1
                }

            }
            return res()
        },

这个时候,文件就上传完成啦

二、下载文件

1.下载插件

我们使用s3的getObject方法获取文件时,获取的是一个readableStream流,所以要使用插件转换成blob文件进行下载

npm i -S binconv

地址:GitHub - nwtgck/binconv-npm: Converters for Blob, Uint8Array, ReadableStream, ArrayBuffer, string in JavaScript/TypeScript

2.下载

//文件下载
        async downLoad(row) {
            let key = row.fid;
            let s3Information = {
                accessKey: "",
                bucket: "",
                endPoint: "",
                secretKey: ""
            }
            //1、判断在bucket中是否存在该文件
            let param = {
                fid: key
            }
//getDownloadUrl这个方法是为了像后端获取用户上传的bucket等信息,这些都可以在前端完成
            await getDownloadUrl(param).then(res => {
                if (res.data.hasOwnProperty("returnCode")) {
                    if (res.data.returnCode == 0) {
                        s3Information = res.data;
                    } else {
                        return this.$message.error(res.data.errMessage);
                    }
                } else {
                    return this.$message.error("错误请求");
                }
            }).catch(err => {
                return this.$message.error("获取文件下载信息过程错误:" + err)
            })
            var s3 = new S3Client({
                endpoint: "https://" + s3Information.endPoint,
                s3ForcePathStyle: true,
                signatureVersion: 'v4',
                region: 'us-east-1',
                forcePathStyle: true,
                credentials: {
                    accessKeyId: s3Information.accessKey,
                    secretAccessKey: s3Information.secretKey,
                }
            });
            let isExistence = await this.getObject(s3Information.bucket, key, s3, row.name)
            if (isExistence == 1) {
                return this.$message.error("bucket中不存在该文件");
            }
        },

放上全部代码

1、前端页面





补充

有很多网友想要与后端相关的文档,所以补充一下

这个是封装的请求

//获取媒体文件列表
export function getMediaFileList(params) {
    return http.get('/mpms/files', params);
}

//获取媒体文件详情
export function getFileDetails(params) {
    return http.get('/mpms/file', params);
}

//上传文件时获取bucket信息
export function fileUpload(params) {
    return http.post('/mpms/file',params);
}

//上传文件并校验成功后,将文件状态改变
export function changeStatus(params) {
    return http.put('/mpms/file', params);
}

//获取文件下载地址
export function getDownloadUrl(params) {
    return http.get('/mpms/file/download', params);
}

这是后端相关的接口文档

仅列出与文件上传相关的fileUpload、changeStatus

fileUpload

Vue使用AWS s3进行大文件的分片上传、断点续传、下载(将文件上传进度显示)_第2张图片

 changeStatus

Vue使用AWS s3进行大文件的分片上传、断点续传、下载(将文件上传进度显示)_第3张图片

你可能感兴趣的:(vue,vue.js,aws)