OSS上传(Java和Js)
- 准备工作
- 创建RAM用户
- 创建角色
- 创建权限策略
- 给角色授予权限策略
- 获取临时访问凭证
- Java普通上传OSS
- Java分片上传OSS
- JS普通上传OSS
- JS分片上传OSS
使用RAM用户或STS方式访问
由于阿里云账号AccessKey拥有所有API访问权限,建议遵循阿里云安全最佳实践。如果部署在服务端可以使用RAM用户或STS来进行API访问或日常运维管控操作,如果部署在客户端请使用STS方式来进行API访问。
本文采用STS方式来实现上传功能,STS可以给第三方提供权限,在考虑接口安全的前提下,还是很合适的,当然如果是自己企业使用的话,也可以直接用RAM用户方式。代码都是类似的
准备工作
登录控制台进入RAM控制台
创建RAM用户
创建完成之后记得复制密钥后面代码里面要用到
返回用户列表,点击添加权限,现在下面权限后点击确定
创建角色
选择阿里云账号,点击下一步
输入名称,点击下一步
点击完成创建
然后角色列表,找到刚刚创建的角色,点击进入
复制角色的ARN,后面的代码里面会用到
创建权限策略
输入脚本
PutObject就是用form表单的方式上传,resource就是bucket资源路径,这个自行修改
{
"Version": "1",
"Statement": [
{
"Effect": "Allow",
"Action": "oss:PutObject",
"Resource": [
"acs:oss:*:*:test/img/*",
"acs:oss:*:*:test/mp4/*"
]
}
]
}
然后点击继续编辑,添加名称后点击 确定即可
给角色授予权限策略
进入角色列表找到刚刚新建的角色,点击添加权限
选择刚刚创建的权限策略,点击确定
获取临时访问凭证
<!--阿里云oss-->
<dependency>
<groupId>com.aliyun.oss</groupId>
<artifactId>aliyun-sdk-oss</artifactId>
<version>3.10.2</version>
</dependency>
注意替换你自己的id 和 secret,这个生成的token有效期默认是3600秒,可以根据业务场景自己调整
public static void main(String[] args) {
// STS接入地址,例如sts.cn-hangzhou.aliyuncs.com。
String endpoint = "sts.cn-hangzhou.aliyuncs.com";
// 填写步骤1生成的RAM用户访问密钥AccessKey ID和AccessKey Secret。
String accessKeyId = "你刚刚创建的RAM用户的AccessKey ID";
String accessKeySecret = "你刚刚创建的RAM用户的AccessKey Secret";
// 填写步骤3获取的角色ARN。
String roleArn = "你刚刚创建的RAM用户的ARN";
// 自定义角色会话名称,用来区分不同的令牌,例如可填写为SessionTest。
String roleSessionName = "SessionTest";
// 以下Policy用于限制仅允许使用临时访问凭证向目标存储空间examplebucket上传文件。
// 临时访问凭证最后获得的权限是步骤4设置的角色权限和该Policy设置权限的交集,即仅允许将文件上传至目标存储空间examplebucket下的exampledir目录。
// 如果policy为空,则用户将获得该角色下所有权限。
String policy = "{\n" +
" \"Version\": \"1\", \n" +
" \"Statement\": [\n" +
" {\n" +
" \"Action\": [\n" +
" \"oss:PutObject\"\n" +
" ], \n" +
" \"Resource\": [\n" +
" \"acs:oss:*:*:test/*\" \n" +
" ], \n" +
" \"Effect\": \"Allow\"\n" +
" }\n" +
" ]\n" +
"}";
// 设置临时访问凭证的有效时间为3600秒。
Long durationSeconds = 3600L;
try {
// regionId表示RAM的地域ID。以华东1(杭州)地域为例,regionID填写为cn-hangzhou。也可以保留默认值,默认值为空字符串("")。
String regionId = "";
// 添加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);
request.setDurationSeconds(durationSeconds);
final AssumeRoleResponse response = client.getAcsResponse(request);
System.out.println("Expiration: " + response.getCredentials().getExpiration());
System.out.println("Access Key Id: " + response.getCredentials().getAccessKeyId());
System.out.println("Access Key Secret: " + response.getCredentials().getAccessKeySecret());
System.out.println("Security Token: " + response.getCredentials().getSecurityToken());
System.out.println("RequestId: " + response.getRequestId());
} catch (ClientException e) {
System.out.println("Failed:");
System.out.println("Error code: " + e.getErrCode());
System.out.println("Error message: " + e.getErrMsg());
System.out.println("RequestId: " + e.getRequestId());
}
}
运行main方法,控制台输出
下面上传代码里用到的id secret token都是用这里生成的,而不是RAM用户的,千万别搞错了
Java普通上传OSS
public static void main(String[] args) {
SimpleDateFormat dateFormat= new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
Date date1 = new Date();
System.out.println("上传开始---" + dateFormat.format(date1));
// Endpoint以杭州为例,其它Region请按实际情况填写。
String endpoint = "oss-cn-hangzhou.aliyuncs.com";
// 填写步骤五获取的临时访问密钥AccessKey ID和AccessKey Secret,非阿里云账号AccessKey ID和AccessKey Secret。
String accessKeyId = "上一步获取的id";
String accessKeySecret = "上一步获取的secret";
// 填写步骤五获取的安全令牌SecurityToken。
String securityToken = "上一步获取的token";
// 创建OSSClient实例。
OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret, securityToken);
// 将本地文件exampletest.txt上传至目标存储空间examplebucket下的目录exampledir。
PutObjectRequest putObjectRequest = new PutObjectRequest("test", "mp4/111.mp4", new File("D:\\test\\111.mp4"));
// ObjectMetadata metadata = new ObjectMetadata();
// 上传文件时设置存储类型。
// metadata.setHeader(OSSHeaders.OSS_STORAGE_CLASS, StorageClass.Standard.toString());
// 上传文件时设置读写权限ACL。
// metadata.setObjectAcl(CannedAccessControlList.Private);
// putObjectRequest.setMetadata(metadata);
// 上传文件。
ossClient.putObject(putObjectRequest);
// 关闭OSSClient。
ossClient.shutdown();
Date date2 = new Date();
System.out.println("上传结束---" + dateFormat.format(date2));
}
运行mian方法成功,去控制台查看是否上传成功,如果没有看到上传的文件,看看是不是路径写错了,或者token过期了,
Java分片上传OSS
分片只有在大文件才能发挥出他的功效,例如1G的文件,如果是几百兆的文件是看不出效果的,有分片上传比普通上传还要慢一些
public static void main(String[] args) throws Exception {
SimpleDateFormat dateFormat= new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
Date date1 = new Date();
System.out.println("上传开始---" + dateFormat.format(date1));
// Endpoint以华东1(杭州)为例,其它Region请按实际情况填写。
String endpoint = "oss-cn-hangzhou.aliyuncs.com";
// 阿里云账号AccessKey拥有所有API的访问权限,风险很高。强烈建议您创建并使用RAM用户进行API访问或日常运维,请登录RAM控制台创建RAM用户。
String accessKeyId = "刚刚获取的id";
String accessKeySecret = "刚刚获取的secret";
String securityToken = "刚刚获取的token";
// 填写Bucket名称,例如examplebucket。
String bucketName = "test";
// 填写Object完整路径,例如exampledir/exampleobject.txt。Object完整路径中不能包含Bucket名称。
String objectName = "mp4/111.mp4";
// 创建OSSClient实例。
OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret,securityToken);
try {
// 创建InitiateMultipartUploadRequest对象。
InitiateMultipartUploadRequest request = new InitiateMultipartUploadRequest(bucketName, objectName);
// 初始化分片。
InitiateMultipartUploadResult upresult = ossClient.initiateMultipartUpload(request);
// 返回uploadId,它是分片上传事件的唯一标识。您可以根据该uploadId发起相关的操作,例如取消分片上传、查询分片上传等。
String uploadId = upresult.getUploadId();
// partETags是PartETag的集合。PartETag由分片的ETag和分片号组成。
List<PartETag> partETags = new ArrayList<PartETag>();
// 每个分片的大小,用于计算文件有多少个分片。单位为字节。
final long partSize = 1 * 1024 * 1024L; //1 MB。
// 填写本地文件的完整路径。
final File sampleFile = new File("D:\\test\\111.mp4");
long fileLength = sampleFile.length();
int partCount = (int) (fileLength / partSize);
if (fileLength % partSize != 0) {
partCount++;
}
// 遍历分片上传。
for (int i = 0; i < partCount; i++) {
long startPos = i * partSize;
long curPartSize = (i + 1 == partCount) ? (fileLength - startPos) : partSize;
InputStream instream = new FileInputStream(sampleFile);
// 跳过已经上传的分片。
instream.skip(startPos);
UploadPartRequest uploadPartRequest = new UploadPartRequest();
uploadPartRequest.setBucketName(bucketName);
uploadPartRequest.setKey(objectName);
uploadPartRequest.setUploadId(uploadId);
uploadPartRequest.setInputStream(instream);
// 设置分片大小。除了最后一个分片没有大小限制,其他的分片最小为100 KB。
uploadPartRequest.setPartSize(curPartSize);
// 设置分片号。每一个上传的分片都有一个分片号,取值范围是1~10000,如果超出此范围,OSS将返回InvalidArgument错误码。
uploadPartRequest.setPartNumber( i + 1);
// 每个分片不需要按顺序上传,甚至可以在不同客户端上传,OSS会按照分片号排序组成完整的文件。
UploadPartResult uploadPartResult = ossClient.uploadPart(uploadPartRequest);
// 每次上传分片之后,OSS的返回结果包含PartETag。PartETag将被保存在partETags中。
partETags.add(uploadPartResult.getPartETag());
}
// 创建CompleteMultipartUploadRequest对象。
// 在执行完成分片上传操作时,需要提供所有有效的partETags。OSS收到提交的partETags后,会逐一验证每个分片的有效性。当所有的数据分片验证通过后,OSS将把这些分片组合成一个完整的文件。
CompleteMultipartUploadRequest completeMultipartUploadRequest =
new CompleteMultipartUploadRequest(bucketName, objectName, uploadId, partETags);
System.out.println("分片---" + partETags.size());
// 完成分片上传。
CompleteMultipartUploadResult completeMultipartUploadResult = ossClient.completeMultipartUpload(completeMultipartUploadRequest);
System.out.println(completeMultipartUploadResult.getETag());
} catch (OSSException oe) {
System.out.println("Caught an OSSException, which means your request made it to OSS, "
+ "but was rejected with an error response for some reason.");
System.out.println("Error Message:" + oe.getErrorMessage());
System.out.println("Error Code:" + oe.getErrorCode());
System.out.println("Request ID:" + oe.getRequestId());
System.out.println("Host ID:" + oe.getHostId());
} catch (ClientException ce) {
System.out.println("Caught an ClientException, which means the client encountered "
+ "a serious internal problem while trying to communicate with OSS, "
+ "such as not being able to access the network.");
System.out.println("Error Message:" + ce.getMessage());
} finally {
if (ossClient != null) {
ossClient.shutdown();
Date date2 = new Date();
System.out.println("上传结束---" + dateFormat.format(date2));
}
}
}
JS普通上传OSS
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>Document</title>
</head>
<body>
<button id="upload">上传</button>
<input id="file" type="file" />
<!--导入SDK文件-->
<script
type="text/javascript"
src="https://gosspublic.alicdn.com/aliyun-oss-sdk-6.16.0.min.js"
></script>
<script type="text/javascript">
const client = new OSS({
// yourRegion填写Bucket所在地域。以华东1(杭州)为例,yourRegion填写为oss-cn-hangzhou。
region: 'oss-cn-hangzhou',
// 从STS服务获取的临时访问密钥(AccessKey ID和AccessKey Secret)。
accessKeyId: '刚刚获取的id',
accessKeySecret: '刚刚获取的secret',
// 从STS服务获取的安全令牌(SecurityToken)。
stsToken: '刚刚获取的token',
// 填写Bucket名称。
bucket: 'test'
});
// 从输入框获取file对象,例如<input type="file" id="file" />。
let data;
// 创建并填写Blob数据。
//const data = new Blob(['Hello OSS']);
// 创建并填写OSS Buffer内容。
//const data = new OSS.Buffer(['Hello OSS']);
const upload = document.getElementById("upload");
const headers = {};
async function putObject (data) {
try {
// 填写Object完整路径。Object完整路径中不能包含Bucket名称。
// 您可以通过自定义文件名(例如exampleobject.txt)或文件完整路径(例如exampledir/exampleobject.txt)的形式实现将数据上传到当前Bucket或Bucket中的指定目录。
// data对象可以自定义为file对象、Blob数据或者OSS Buffer。
const result = await client.put(
"mp4/111.mp4",
data
//{headers}
);
console.log(result);
} catch (e) {
console.log(e);
}
}
upload.addEventListener("click", () => {
data = document.getElementById("file").files[0];
putObject(data);
});
</script>
</body>
</html>
JS分片上传OSS
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>Document</title>
</head>
<body>
<button id="submit">上传</button>
<input id="file" type="file" />
<!--导入sdk文件-->
<script
type="text/javascript"
src="https://gosspublic.alicdn.com/aliyun-oss-sdk-6.16.0.min.js"
></script>
<script type="text/javascript">
const client = new OSS({
// yourRegion填写Bucket所在地域。以华东1(杭州)为例,Region填写为oss-cn-hangzhou。
region: "oss-cn-hangzhou",
// 从STS服务获取的临时访问密钥(AccessKey ID和AccessKey Secret)。
accessKeyId: "刚刚获取的id",
accessKeySecret: "刚刚获取的secret",
// 从STS服务获取的安全令牌(SecurityToken)。
stsToken: "刚刚获取的token",
// 填写Bucket名称,例如examplebucket。
bucket: "test",
});
const headers = {
// 指定该Object被下载时的网页缓存行为。
"Cache-Control": "no-cache",
// 指定该Object被下载时的名称。
"Content-Disposition": "111.mp4",
// 指定该Object被下载时的内容编码格式。
"Content-Encoding": "utf-8",
// 指定过期时间,单位为毫秒。
"Expires": "1000",
// 指定Object的存储类型。
"x-oss-storage-class": "Standard",
// 指定Object标签,可同时设置多个标签。
"x-oss-tagging": "Tag1=1&Tag2=2",
// 指定初始化分片上传时是否覆盖同名Object。此处设置为true,表示禁止覆盖同名Object。
"x-oss-forbid-overwrite": "true",
};
// 指定上传到examplebucket的Object名称,例如exampleobject.txt。
const name = "111.mp4";
// 获取DOM。
const submit = document.getElementById("submit");
const options = {
// 获取分片上传进度、断点和返回值。
progress: (p, cpt, res) => {
console.log(p);
},
// 设置并发上传的分片数量。
parallel: 4,
// 设置分片大小。默认值为1 MB,最小值为100 KB。
partSize: 1024 * 1024,
// headers,
// 自定义元数据,通过HeadObject接口可以获取Object的元数据。
meta: { year: 2020, people: "test" },
mime: "text/plain",
};
// 监听按钮。
submit.addEventListener("click", async () => {
try {
const data = document.getElementById("file").files[0];
// 分片上传。
const res = await client.multipartUpload(name, data, {
...options,
// 设置上传回调。
});
console.log(res)
} catch (err) {
console.log(err);
}
});
</script>
</body>
</html>