将AWS S3大文件文件上传相关的API集成为js文件,功能包括 多文件并行上传、文件分片上传、断点续传、文件分片合成、上传暂停、取消上传、文件上传进度条显示_初八不乖的博客-CSDN博客
AWS S3的官方文档(GetObject - Amazon Simple Storage Service)
npm install @aws-sdk/client-s3
const {
S3Client,
CreateMultipartUploadCommand,
ListMultipartUploadsCommand,
GetObjectCommand,
UploadPartCommand,
CompleteMultipartUploadCommand,
AbortMultipartUploadCommand
} = require("@aws-sdk/client-s3");
//这里显示的是后面要用到的s3中的方法,具体怎么使用,后面会讲到
(存储文件的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); // 成功
});
在每一个文件上传时,都要先与服务器建立连接,并获取唯一的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()
},
注意: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)//分片文件
}
//上传一个分片
//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();
},
注意:在分片上传完成,并且合并之后,系统会自动断开连接;如果是发异常,如上传分片失败等,需要手动断开连接
//将分片合并
//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()
},
这个时候,文件就上传完成啦
我们使用s3的getObject方法获取文件时,获取的是一个readableStream流,所以要使用插件转换成blob文件进行下载
npm i -S binconv地址:GitHub - nwtgck/binconv-npm: Converters for Blob, Uint8Array, ReadableStream, ArrayBuffer, string in JavaScript/TypeScript
//文件下载
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中不存在该文件");
}
},
上传媒体文件
文件名
{{ scope.row.fid }}
是
否
详情
下载
删除
文件详情
提示:双击弹窗头部,可使弹窗全屏展示
{{ myDetails.fid }}
{{ myDetails.name }}
{{ myDetails.size }}
{{ myDetails.suffix }}
{{ myDetails.creatAt }}
上传成功
待上传
待上传
已删除
已删除
下载
{{ myDetails.meta }}
有很多网友想要与后端相关的文档,所以补充一下
这个是封装的请求
//获取媒体文件列表
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
changeStatus