阿里云oss 前端通过stsToken,普通上传、分片上传、断点续传(单文件和批量上传)

一、获取sts相关信息

public static AliOssStsVo getStsToken() {
        // STS接入地址,例如sts.cn-hangzhou.aliyuncs.com。
        String endpoint = "sts.cn-hangzhou.aliyuncs.com";
        // 填写步骤1生成的访问密钥AccessKey ID和AccessKey Secret。
        String AccessKeyId = "";
        String accessKeySecret = "";
        // 填写步骤3获取的角色ARN。
        String roleArn = "";
        // 自定义角色会话名称,用来区分不同的令牌,例如可填写为SessionTest。
        String roleSessionName = "ramosstest";
        // 以下Policy用于限制仅允许使用临时访问凭证向目标存储空间examplebucket上传文件。
        // 临时访问凭证最后获得的权限是步骤4设置的角色权限和该Policy设置权限的交集,即仅允许将文件上传至目标存储空间examplebucket下的exampledir目录。
        String policy = "{\n" +
                "    \"Version\": \"1\", \n" +
                "    \"Statement\": [\n" +
                "        {\n" +
                "            \"Action\": [\n" +
                "                \"oss:PutObject\"\n" +
                "            ], \n" +
                "            \"Resource\": [\n" +
                "                \"acs:oss:*:*:bucket-qi/*\" \n" +
                "            ], \n" +
                "            \"Effect\": \"Allow\"\n" +
                "        }\n" +
                "    ]\n" +
                "}";
        AliOssStsVo aliOssStsVo = new AliOssStsVo();
        // regionId表示RAM的地域ID。以华东1(杭州)地域为例,regionID填写为cn-hangzhou。也可以保留默认值,默认值为空字符串("")。
        try {
            String regionId = "cn-hangzhou";
            // 添加endpoint。适用于Java SDK 3.12.0及以上版本。
            DefaultProfile.addEndpoint(regionId, "Sts", endpoint);
            // 添加endpoint。适用于Java SDK 3.12.0以下版本。
            // DefaultProfile.addEndpoint("",regionId, "Sts", endpoint);
            // 构造default profile。
            IClientProfile profile = DefaultProfile.getProfile(regionId, AccessKeyId, accessKeySecret);
            // 构造client。
            DefaultAcsClient client = new DefaultAcsClient(profile);
            final AssumeRoleRequest request = new AssumeRoleRequest();
            // 适用于Java SDK 3.12.0及以上版本。
            request.setSysMethod(MethodType.POST);
            // 适用于Java SDK 3.12.0以下版本。
            //request.setMethod(MethodType.POST);
            request.setRoleArn(roleArn);
            request.setRoleSessionName(roleSessionName);
//            request.setPolicy(policy); // 如果policy为空,则用户将获得该角色下所有权限。
            request.setDurationSeconds(3600L); // 设置临时访问凭证的有效时间为3600秒。
            final AssumeRoleResponse response = client.getAcsResponse(request);
            aliOssStsVo.setAccessKeyId(response.getCredentials().getAccessKeyId());
            aliOssStsVo.setAccessKeySecret(response.getCredentials().getAccessKeySecret());
            aliOssStsVo.setSecurityToken(response.getCredentials().getSecurityToken());
            aliOssStsVo.setExpiration(response.getCredentials().getExpiration());
//
        } catch (ClientException e) {
            e.printStackTrace();
        }
        return aliOssStsVo;
    }

二、前端配置

安装ali-oss ,npm iali-oss

1、组件

<template>
	<div>
		<h2>单文件上传</h2>
		<el-button @click="ordinaryupload">普通上传</el-button>
		<el-button type="primary" @click="partUpload">分片上传</el-button>
		<el-button type="success" @click="pause">暂停</el-button>
		<el-button type="info" @click="resumeUpload"> 恢复上传</el-button>
		<div style="display: flex;margin-top: 20px;">
			<span v-text="`${file.name}(${(file.size/(1024*1024)).toFixed(1)}MB)`" style="margin-right: 15px;"
				v-show="file.name"></span>
			<div style="width: 30%;" v-show="progress>0">
				<el-progress :percentage="parseInt((progress*100))" :format="format" :text-inside="true"
					:stroke-width="20"></el-progress>
			</div>
		</div>
		<h2>多文件上传</h2>
		<div>
			<el-button @click="chooseFiles">多文件选择</el-button>
			<el-button @click="allUpload" type="primary" :disabled="isDisable">全部上传</el-button>
		</div>
		<div v-for="(item,index) in  fileList" :key="item.name" style="display: flex; padding:10px  20px; ">
			<div v-text="item.name" style="width: 20%;"> </div>
			<div style="margin: 0 20px;width: 40%;">
				<el-progress :percentage="parseInt(item.progress*100)" :format=format1>
				</el-progress>
			</div>
			<div style="width: 20%;">
				<el-button size="mini" v-text="item.isStop?'上传':'暂停'" :type="item.isStop?'success':'warning'"
					@click="toggleUpload(item)" v-show="!item.fileUrl"></el-button>
				<el-button size="mini" type="danger" @click="cancelUpload(item,index)" v-show="!item.fileUrl">取消
				</el-button>
				<i class="el-icon-circle-check" style="color: green;" v-show="item.fileUrl"></i>
			</div>
		</div>
	</div>
</template>

<script>
	import {
		initOssClient,
		upload,
		partUpload,
		resumeUpload,
		ossClient,
		getStsToken,
		abortUpload
	} from '../api/aliOssUpload.js'
	import OSS from 'ali-oss'
	export default {
		data() {
			return {
				client: {},
				checkPoint: {},
				file: {},
				dir: {},
				progress: 0,
				fileList: [],
				isDisable: false

			}
		},

		methods: {

			format1(p) {
				return p === 100 ? '完成' : p + "%"
			},
			// 取消上传并删除已上传的分片
			cancelUpload(item, index) {
				if (Object.keys(item.client).length > 0) {
					abortUpload(item.client, item.checkPoint.uploadId, item.checkPoint.name)
				}
				this.fileList.splice(index, 1)
			},
			// 切换上传与暂停
			async toggleUpload(item) {
				item.isStop = 1 - item.isStop
				if (item.isStop) {
					item.client.cancel()
				} else {
					// 上传
					if (Object.keys(item.client).length === 0) {
						const {
							client,
							dir
						} = await initOssClient()
						item.client = client
						item.dir = dir
					}
					const resp = await resumeUpload(item.client, item.file, item.dir, (p, cpt) => {
						item.progress = p
						item.checkPoint = cpt
					}, item.checkPoint)
					if (resp) {
						item.fileUrl = resp[0].split("?")[0]
					}
				}
			},
			// 全部上传
			async allUpload() {
				if (this.fileList.some(item => item.isStop === 0)) {
					return
				}
				const {
					data: res
				} = await getStsToken()
				for (let item of this.fileList) {
					if (Object.keys(item.client).length === 0) {
						const client = ossClient(res)
						item.client = client
						item.dir = res.data.dir
					}
					item.isStop = 0
					const resp = partUpload(item.client, item.file, item.dir, (p, cpt) => {
						item.progress = p
						item.checkPoint = cpt
					}).then(res => {
						if (res) {
							item.fileUrl = res[0].split("?")[0]
						}

					})
				}
				this.isDisable = true
			},
			async chooseFiles() {
				let files = await this.$chooseFile({
					multiple: 'multiple'
				})
				for (var i = 0; i < files.length; i++) {
					let item = {}
					item.file = files[i]
					item.name = `${files[i].name}(${(files[i].size/(1024*1024)).toFixed(1)}MB)`
					item.isStop = 1
					item.progress = 0,
						item.client = {}
					item.dir = ''
					item.checkPoint = {}
					item.fileUrl = ''
					this.fileList.push(item)
				}
				this.isDisable = false
			},

			format() {
				return (this.progress * 100).toFixed(2) + '%'
			},

			async init() {
				if (Object.keys(this.client).length === 0) {
					const {
						client,
						dir
					} = await initOssClient()
					this.client = client
					this.dir = dir
					console.log(this.client);
				}
			},
			// 普通上传
			async ordinaryupload() {
				this.init()
				let files = await this.$chooseFile()
				let url = await upload(this.client, files[0], this.dir)
				console.log(url);

			},
			// 分片上传
			async partUpload() {
				this.init()
				let files = await this.$chooseFile()
				this.file = files[0]
				const resp = await partUpload(this.client, this.file, this.dir, (p, cpt) => {
					this.progress = p
					this.checkPoint = cpt
				})
				console.log(resp);
			},

			// 断点续传
			async resumeUpload() {
				const resp = await resumeUpload(this.client, this.file, this.dir, (p, cpt) => {
					this.progress = p
					this.checkPoint = cpt
				}, this.checkPoint)
				console.log(resp);
			},
			// 暂停上传
			pause() {
				this.client.cancel()
			},
		},
	}
</script>

<style scoped>

</style>

2、api

import OSS from 'ali-oss'
import request from '../utils/request'

function getStsToken() {
	return request({
		url: '/getStsUpload',
		method: 'get'
	})
}
// 从后端获取ststoken 并初始化ossclient,通过promise返回ossclient和stsToken
export async function initOssClient() {
	const {
		data: res
	} = await getStsToken()
	if (res.code === 200) {
		const client = new OSS({
			region: res.data.region, // 根据那你的Bucket地点来填写
			accessKeyId: res.data.accessKeyId, // 自己账户的accessKeyId或临时秘钥
			accessKeySecret: res.data.accessKeySecret, // 自己账户的accessKeySecret或临时秘钥
			stsToken: res.data.securityToken, //  从STS服务获取的安全令牌(SecurityToken)。
			bucket: res.data.bucket, // bucket名字
			refreshSTSToken: async () => {
				// 向您搭建的STS服务获取临时访问凭证。
				const {
					data: res
				} = await getSts()
				return {
					accessKeyId: res.data.accessKeyId, // 自己账户的accessKeyId或临时秘钥
					accessKeySecret: res.data.accessKeySecret, // 自己账户的accessKeySecret或临时秘钥
					stsToken: res.data.securityToken, //  从STS服务获取的安全令牌(SecurityToken)。
				}
			},
			// 刷新临时访问凭证的时间间隔,单位为毫秒。
			refreshSTSTokenInterval: 3600 * 1000
		})

		return {
			client: client,
			dir: res.data.dir
		}
	}
}

/**
 * 普通上传
 * @param {Object} client
 * @param {Object} file
 * @param {Object} dir
 */
export async function upload(client, file, dir) {
	const {
		url
	} = await client.put(dir + file.name, file)
	return url
}
/**
 * 分片上传
 * @param {Object} client oss客户端
 * @param {Object} file 上传的文件
 * @param {Object} dir 上传oss的文件夹 
 * @param {Object} progressCallback 分片进度回调
 */
export async function partUpload(client, file, dir, progressCallback) {
	try {
		let options = {
			// 获取分片上传进度、断点和返回值。
			progress: progressCallback,

			// 设置并发上传的分片数量。
			parallel: 8,
			// 设置分片大小。默认值为1 MB,最小值为100 KB。
			partSize: 100 * 1024,
			mime: file.type
		}
		const {
			res: resp
		} = await client.multipartUpload(dir + file.name, file, options)
		return resp.requestUrls
	} catch (e) {
		console.log(e);
	}
}
/**
 * 断点续传
 * @param {Object} client oss客户端
 * @param {Object} file 上传的文件
 * @param {Object} dir  oss上传的文件夹
 * @param {Object} progressCallback 分片回调进度
 * @param {Object} checkPoint  断点
 */
export async function resumeUpload(client, file, dir, progressCallback, checkPoint) {
	try {
		let options = {
			// 获取分片上传进度、断点和返回值。
			progress: progressCallback,
			// 断点
			checkpoint: checkPoint,
		}
		const {
			res: resp
		} = await client.multipartUpload(dir + file.name, file, options)
		return resp.requestUrls
	} catch (e) {
		console.log(e);
	}

}
/**
 * 结束上传并删除碎片
 * @param {Object} client
 * @param {Object} uploadId
 * @param {Object} name
 */
export  function abortUpload(client,uploadId,name){
	client.abortMultipartUpload(name,uploadId)
}

三、演示

在这里插入图片描述

注意:此方式页面刷新或者浏览器关闭,断点续传失效。解决方式:你可将上传的文件和暂停时的断点数据保存在localstorage中,但是这样也存在问题,当你换浏览器断点续传同样失效。

  • 3
    点赞
  • 27
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
阿里云OSS分片文件上传是一种将大文件分成多个数据块(Part)进行上传的方法,以实现高效的文件上传断点续传功能。这种分片上传的方法可以应用于需要传输大文件的场景,比如视频点播文件等。 分片上传的步骤包括初始化一个分片上传事件、上传分片和完成分片上传。首先,需要初始化一个分片上传事件,获取一个唯一的上传ID和用于标识上传文件名。然后,将文件分成多个数据块,逐个上传每个数据块,并记录每个数据块的编号和ETag。最后,通过调用完成分片上传的接口,将所有上传的数据块合并成一个完整的文件。 在分片上传过程中,可以通过监控上传进度,实时获取上传的数据块数目和总数据块数,从而了解上传的进度情况。可以使用两种方式来实现监控上传进度,一种是通过查询上传事件的接口来获取已经上传的数据块数目和总数据块数,另一种是通过每个数据块上传完成时的回调来更新上传进度。 在使用分片上传时,需要注意一些事项。首先,每个数据块的大小可以根据实际需求进行调整,但要遵循OSS的限制条件。其次,上传数据块时需要保证数据块的顺序和完整性,以确保数据块可以正确地组合成完整的文件。最后,完成分片上传后,需要注意保存上传ID和ETag,以便之后可以进行断点续传操作。 总结来说,阿里云OSS分片文件上传是一种将大文件分成多个数据块进行上传的方法,可以实现高效的文件上传断点续传功能。通过分片上传,可以有效地应对大文件传输的需求,并且通过监控上传进度和注意事项,可以更好地控制和管理文件上传的过程。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* *3* [阿里云对象存储OSS-分片上传](https://blog.csdn.net/Morris_/article/details/102813989)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 100%"] [ .reference_list ]

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值