大文件分片上传: 1、确认分块的维度,创建分块上传,获取到uploadId作为分块上传标识 2、传入uploadId进行分块上传,获取到每个分块独有的Etag 3、成功上传所有相关部分后,将分块整合成一个完整的文件。对象存储服务将按部件编号升序连接所有部件以创建新文件
import {
ossInfo,
reviewUrl,
eosInfo,
getEosSign,
uploadEosCallback,
} from "@/api/publicFile";
import { message } from "ant-design-vue";
export const uploadFile = async (params) => {
if(!params.file) {
message.error("文件上传失败!")
return
}
return uploadByEos(params)
};
/** eos 上传 */
const uploadByEos = async params => {
console.log(params.file.size)
return params.file.size > 1024 * 1024 * 50
? uploadByEosMultipart(params)
: uploadByEosDirect(params)
}
/** eos 直传 */
const uploadByEosDirect = async params => {
const res = await getEosSign()
let s3 = new AWS.S3({
accessKeyId: res.data?.accessKeyId,
secretAccessKey: res.data?.secretAccessKey,
endpoint: res.data?.endpoint,
region: res.data?.region,
sessionToken: res.data?.sessionToken
})
const fileInfo = {
Key: `${res.data?.key}${params.file.name}`,
Bucket: res.data?.bucket,
ContentType: params.file.type,
Body: params.file,
}
return new Promise((resolve,reject) => {
return s3.putObject(fileInfo, async function(err, data){
if(err) {
reject(err)
return message.error(err)
}
const fileData = {
etag: JSON.parse(data.ETag),
key: `${res.data?.key}${params.file.name}`,
filename: params.file.name,
size: params.file.size
}
const value = await uploadEosCallback(fileData)
resolve(value)
})
})
}
/** eos 分片 */
const uploadByEosMultipart = async params => {
const res = await getEosSign()
const s3 = new AWS.S3({
accessKeyId: res.data?.accessKeyId,
secretAccessKey: res.data?.secretAccessKey,
endpoint: res.data?.endpoint,
region: res.data?.region,
sessionToken: res.data?.sessionToken
})
const key = `${res.data?.key}${params.file.name}`
const bucket = res.data?.bucket
const { UploadId: uploadId } = await createMultipartUpload({
key,
file: params.file,
bucket,
s3
})
const parts = await uploadEosPart({ key, file: params.file, bucket, uploadId, s3 })
const { ETag } = await completeUploadEosPart({ key, bucket, uploadId, parts, s3 })
const fileData = {
etag: ETag,
key,
filename: params.file.name,
size: params.file.size
}
return await uploadEosCallback(fileData)
}
const createMultipartUpload = ({ key, file, bucket, s3 }) => {
let fileInfo = {
Key: key,
Bucket: bucket,
// ACL: "private"
}
return new Promise((resolve, reject) => {
s3.createMultipartUpload(
fileInfo,
(err, data) => {
if(err) {
reject(err)
return message.error(err)
}
resolve(data)
}
)
})
}
const uploadEosPart = async ({ key, file, bucket, uploadId, s3 }) => {
const chunkSize = 1024 * 1024 * 5 // 每个切片的大小
const totalChunks = Math.ceil(file.size / chunkSize)
const parts = []
for(let i = 0; i < totalChunks; i++) {
const start = i * chunkSize
const end = start + chunkSize
const value = {
Body: file.slice(start, end),
Bucket: bucket,
Key: key,
PartNumber: i + 1 ,
UploadId: uploadId
}
const { ETag } = await uploadEosPartApi(value, { s3 })
parts.push({ ETag, PartNumber: value.PartNumber })
}
return parts
}
// eos 分片上传 api promise
const uploadEosPartApi = (value, { s3 }) => {
return new Promise((resolve, reject) => {
s3.uploadPart(value, function(err, data) {
if(err) {
reject(err)
return message.error(err)
}
resolve(data)
})
})
}
// eos 完成分片上传 api promise
const completeUploadEosPart= ({ key, bucket, uploadId, parts, s3 }) => {
const fileData = {
Bucket: bucket,
Key: key,
MultipartUpload: {
Parts: parts
},
UploadId: uploadId
}
return new Promise((resolve, reject) => {
s3.completeMultipartUpload(fileData, function(err, data) {
if(err) {
reject(err)
return message.error(err)
}
resolve(data)
})
})
}