obs临时url分段上传实例

需求:由于上传文件过大需要对文件进行切割 然后分段上传。

优点:此处使用临时url操作,前端完全不需要使用obs提供的jdk, obs账号密码由后端保存,大大提高了安全性。

流程:后台提供两个接口,分别是:

1.从后台获取临时操作url 用于初始化 并获取uploadId

2.后台获取临时分段操作url 用于分段上传 

/**
 * 临时url上传 分段
 */
export async function uploadMulFileToObsTemp(
	obsType: string,
	file: File,
	filePath: string,
	callback: Function
) {
	const uploadId = await getTemMulObsSignedUrlUploadId(obsType, filePath);
	// 第一步 分段
	const chunks = await sliceFile(file);
	const promiseList: any = [];
	if (chunks.length) {
		chunks.forEach((f, i) => {
			const itemApi = mulPartUpload(filePath, f, uploadId, i + 1);
			promiseList.push(itemApi);
		});
	}
	// 等待分段上传完成 发送合并合并段
	Promise.all(promiseList).then(async (result) => {
		if (result.length) {
			// 第二 分段上完成后 合并处理
			const obsSigned = await getTmpObsMergeSignedUrl(
				filePath,
				'POST',
				uploadId,
				'application/xml'
			);
            // 后台要求上传格式xml
			let content = `<CompleteMultipartUpload>`;
			result.forEach((f) => {
				content += `<Part>`;
				content += `<PartNumber>${f.partNum}</PartNumber>`;
				content += `<ETag>${f.etag}</ETag>`;
				content += `</Part>`;
			});
			content += `</CompleteMultipartUpload>`;

			mergePartUpload(obsSigned, content).then(async (res: any) => {
				if (res.status === 200) {
					const url = window.URL.createObjectURL(file);
					callback(url);
				} else {
					callback(false);
				}
			});
		}
	});
}

// 分段 上传
export async function mulPartUpload(
	filePath: string,
	file: File | Blob,
	uploadId: string,
	partNumber: string | number,
	t = 2
) {
	const obsSigned: any = await getTmpObsMulSignedUrl(
		filePath,
		'PUT',
		partNumber,
		uploadId
	);
	return new Promise((resolve, reject) => {
		if (obsSigned.actualSignedRequestHeaders.Host) {
			delete obsSigned.actualSignedRequestHeaders.Host;
		}
		const reopt: any = {
			method: 'PUT',
			url: obsSigned.signedUrl,
			withCredentials: false,
			headers: obsSigned.actualSignedRequestHeaders || {},
			headersType: 'application/x-www-form-urlencoded',
			maxRedirects: 0,
			responseType: 'text',
			data: file,
			validateStatus: function (status: number) {
				return status >= 200;
			},
		};
		axios
			.request(reopt)
			.then(function (response) {
				console.log(response);
				if (response.status < 300) {
					const part = {
						partNum: Number(partNumber),
						etag: JSON.parse(response.headers.etag),
					};
					resolve(part);
				} else {
					reject(response);
				}
			})
			.catch(function (err) {
				console.log('Upload Object using temporary signature failed!');
				console.log(err);
				t--;
				if (t > 0) {
					// 失败后  重传2次
					mulPartUpload(filePath, file, uploadId, partNumber, t);
				} else {
					// 重传2次后还是失败 就取消上传任务
					cancelPartUpload(filePath, uploadId);
				}
				reject(err);
			});
	});
}

// 取消分段上传任务
export async function cancelPartUpload(filePath: string, uploadId: string) {
	const obsSigned: any = await getTmpObsMergeSignedUrl(
		filePath,
		'DELETE',
		uploadId
	);
	return new Promise((resolve, reject) => {
		const reopt: any = {
			method: 'DELETE',
			url: obsSigned.signedUrl,
			withCredentials: false,
			headers: obsSigned.actualSignedRequestHeaders || {},
			maxRedirects: 0,
			data: null,
			responseType: 'text',
			validateStatus: function (status: number) {
				return status >= 200;
			},
		};
		axios
			.request(reopt)
			.then(function (response) {
				if (response.status < 300) {
					resolve(response);
				} else {
					reject(response);
				}
			})
			.catch(function (err) {
				console.log(err);
				reject(err);
			});
	});
}


// 发送合并分段请求
export async function mergePartUpload(obsSigned: any, content: string) {
	return new Promise((resolve, reject) => {
		const reopt: any = {
			method: 'POST',
			url: obsSigned.signedUrl,
			withCredentials: false,
			headers: obsSigned.actualSignedRequestHeaders || {},
			maxRedirects: 0,
			responseType: 'text',
			data: content,
			validateStatus: function (status: number) {
				return status >= 200;
			},
		};
		axios
			.request(reopt)
			.then(function (response) {
				if (response.status < 300) {
					resolve(response);
				} else {
					reject(response);
				}
			})
			.catch(function (err) {
				console.log(err);
				reject(err);
			});
	});
}

// 分段大小 50M
export const sliceFile = (file: File | Blob, chunkSize = FILESIZE) => {
	// 50Mb
	const chunkCount = Math.ceil(file.size / chunkSize);
	return new Array(chunkCount).fill(null).map((_, i) => {
		return file.slice(i * chunkSize, (i + 1) * chunkSize);
	});
};

/**
 * 获取临时URL 分段上传
 * @param obsType
 * @param objectKey
 * @param operationType
 */
export async function getTmpObsMulSignedUrl(
	objectKey: string,
	operationType: string,
	partNumber?: string | number,
	uploadId?: string
) {
	const config = {};
	await postTemporarySignature({
		data: {
			path: objectKey,
			method: operationType,
			queryParams: { partNumber, uploadId },
		},
	}).then(async (res: any) => {
		if (res.data.success) {
			await Object.assign(config, res.data.data);
		}
	});
	return config;
}

/**
 * 获取 合并段 url  分段
 */
export async function getTmpObsMergeSignedUrl(
	objectKey: string,
	operationType: string,
	uploadId: string,
	contentType?: string
) {
	const config = {};
	await postTemporarySignature({
		data: {
			path: objectKey,
			method: operationType,
			contentType: contentType,
			queryParams: { uploadId },
		},
	}).then(async (res: any) => {
		if (res.data.success) {
			await Object.assign(config, res.data.data);
		}
	});
	return config;
}

// 获取临时 分段签名 url 后台接口二
export const postTemporarySignature = ({ data }: any) => {
	// 权限判断
	return post({
		url: 'open/admin/obs/postTemporarySignature',
		method: 'post',
		data,
		headers: {
			headersType: 'application/x-www-form-urlencoded',
		},
	});
};

// 获取 obs 分段 uploadid
export async function getTemMulObsSignedUrlUploadId(
	obsType: string,
	objectKey: string
) {
	let uploadid = '';
	await initMultipartUpload({
		data: { path: objectKey },
	}).then(async (res: any) => {
		if (res.data.success) {
			uploadid = res.data.data;
		}
	});
	return uploadid;
}

/**
 * 获取POST临时签名 分段  后台接口一
 * @param data
 */
export const initMultipartUpload = ({ data }: any) => {
	// 权限判断
	return post({
		url: 'open/admin/obs/initMultipartUpload',
		data,
		headers: {
			headersType: 'application/x-www-form-urlencoded',
		},
	});
};

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值