1、简单上传
简单上传是指通过PutObject方法上传单个文件(Object)。简单上传包括流式上传和文件上传,流式上传使用InputStream作为OSS文件的数据源,文件上传使用本地文件作为OSS文件的数据源。本文介绍如何使用流式上传和文件上传方式上传文件。包括流式上传和文件上传。最大不能超过5GB。
1.1、流式上传
使用流式上传,您可以将数据流上传到OSS文件。
说明:如果OSS文件存在,则上传的数据会覆盖该文件的内容;如果OSS文件不存在,则会新建该文件。
1.1.1、上传字符串
1.1.1.1、代码示例
package com.dmj.cn;
import com.aliyun.oss.ClientException;
import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClientBuilder;
import com.aliyun.oss.OSSException;
import com.aliyun.oss.common.auth.CredentialsProviderFactory;
import com.aliyun.oss.common.auth.EnvironmentVariableCredentialsProvider;
import com.aliyun.oss.internal.OSSHeaders;
import com.aliyun.oss.model.PutObjectRequest;
import com.aliyun.oss.model.StorageClass;
import java.io.ByteArrayInputStream;
public class Demo {
/**
* endpoint是访问OSS的域名。
* 参考https://help.aliyun.com/zh/oss/user-guide/regions-and-endpoints?spm=a2c4g.11186623.0.0.563479cc0ioUZ7
*/
private static String endpoint = "<yourEndpoint>";
/**
* accessKeyId和accessKeySecret是OSS的访问密钥,
* 参考:https://help.aliyun.com/zh/oss/product-overview/what-is-oss?spm=a2c4g.11186623.0.i42
* 注意:accessKeyId和accessKeySecret前后都没有空格,从控制台复制时请检查并去除多余的空格。
*/
private static String accessKeyId = "<yourAccessKeyId>";
private static String accessKeySecret = "<yourAccessKeySecret>";
/**
* Bucket用来管理所存储Object的存储空间,
* 参考:https://help.aliyun.com/zh/oss/user-guide/buckets-10/?spm=a2c4g.11186623.0.0.47ba2cd9binPXN
* Bucket命名规范如下:Bucket名称在OSS范围内必须全局唯一,只能包括小写字母,数字和短横线(-),必须以小写字母或者数字开头,长度必须在3-63字节之间。
*/
private static String bucketName = "<yourBucketName>";
public static void main(String[] args) throws Exception {
// 填写Object完整路径,例如 dmjxsy/demo.txt。Object完整路径中不能包含Bucket名称。
String objectName = "dmjxsy/demo.txt";
// 创建OSSClient实例。
OSS ossClient = new OSSClientBuilder().build(endpoint,accessKeyId,secretAccessKey);
try {
String content = "Hello DMJXSY";
// 创建PutObjectRequest对象。
PutObjectRequest putObjectRequest = new PutObjectRequest(bucketName, objectName, new ByteArrayInputStream(content.getBytes()));
//上传字符串。
ossClient.putObject(putObjectRequest);
} 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();
}
}
}
}
1.1.1.2、执行结果
1.1.2、上传Byte数组
1.1.2.1、代码示例
package com.dmj.cn;
import com.aliyun.oss.ClientException;
import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClientBuilder;
import com.aliyun.oss.OSSException;
import com.aliyun.oss.common.auth.CredentialsProviderFactory;
import com.aliyun.oss.common.auth.EnvironmentVariableCredentialsProvider;
import com.aliyun.oss.internal.OSSHeaders;
import com.aliyun.oss.model.PutObjectRequest;
import com.aliyun.oss.model.StorageClass;
import java.io.ByteArrayInputStream;
public class Demo {
/**
* endpoint是访问OSS的域名。
* 参考https://help.aliyun.com/zh/oss/user-guide/regions-and-endpoints?spm=a2c4g.11186623.0.0.563479cc0ioUZ7
*/
private static String endpoint = "<yourEndpoint>";
/**
* accessKeyId和accessKeySecret是OSS的访问密钥,
* 参考:https://help.aliyun.com/zh/oss/product-overview/what-is-oss?spm=a2c4g.11186623.0.i42
* 注意:accessKeyId和accessKeySecret前后都没有空格,从控制台复制时请检查并去除多余的空格。
*/
private static String accessKeyId = "<yourAccessKeyId>";
private static String accessKeySecret = "<yourAccessKeySecret>";
/**
* Bucket用来管理所存储Object的存储空间,
* 参考:https://help.aliyun.com/zh/oss/user-guide/buckets-10/?spm=a2c4g.11186623.0.0.47ba2cd9binPXN
* Bucket命名规范如下:Bucket名称在OSS范围内必须全局唯一,只能包括小写字母,数字和短横线(-),必须以小写字母或者数字开头,长度必须在3-63字节之间。
*/
private static String bucketName = "<yourBucketName>";
public static void main(String[] args) throws Exception {
// 填写Object完整路径,例如 dmjxsy/demo.txt。Object完整路径中不能包含Bucket名称。
String objectName = "dmjxsy/demo.txt";
// 创建OSSClient实例。
OSS ossClient = new OSSClientBuilder().build(endpoint,accessKeyId,secretAccessKey);
try {
byte[] bytes = "Hello DMJXSY 上传Byte数组".getBytes();
// 创建PutObjectRequest对象。
PutObjectRequest putObjectRequest = new PutObjectRequest(bucketName, objectName, new ByteArrayInputStream(bytes));
//上传字符串。
ossClient.putObject(putObjectRequest);
} 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();
}
}
}
}
1.1.2.2、执行结果
1.1.3、上传网络流
1.1.3.1、代码示例
package com.dmj.cn;
import com.aliyun.oss.ClientException;
import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClientBuilder;
import com.aliyun.oss.OSSException;
import com.aliyun.oss.common.auth.CredentialsProviderFactory;
import com.aliyun.oss.common.auth.EnvironmentVariableCredentialsProvider;
import com.aliyun.oss.internal.OSSHeaders;
import com.aliyun.oss.model.PutObjectRequest;
import com.aliyun.oss.model.StorageClass;
import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.net.URL;
public class Demo {
/**
* endpoint是访问OSS的域名。
* 参考https://help.aliyun.com/zh/oss/user-guide/regions-and-endpoints?spm=a2c4g.11186623.0.0.563479cc0ioUZ7
*/
private static String endpoint = "<yourEndpoint>";
/**
* accessKeyId和accessKeySecret是OSS的访问密钥,
* 参考:https://help.aliyun.com/zh/oss/product-overview/what-is-oss?spm=a2c4g.11186623.0.i42
* 注意:accessKeyId和accessKeySecret前后都没有空格,从控制台复制时请检查并去除多余的空格。
*/
private static String accessKeyId = "<yourAccessKeyId>";
private static String accessKeySecret = "<yourAccessKeySecret>";
/**
* Bucket用来管理所存储Object的存储空间,
* 参考:https://help.aliyun.com/zh/oss/user-guide/buckets-10/?spm=a2c4g.11186623.0.0.47ba2cd9binPXN
* Bucket命名规范如下:Bucket名称在OSS范围内必须全局唯一,只能包括小写字母,数字和短横线(-),必须以小写字母或者数字开头,长度必须在3-63字节之间。
*/
private static String bucketName = "<yourBucketName>";
public static void main(String[] args) throws Exception {
// 填写Object完整路径,例如 dmjxsy/demo.txt。Object完整路径中不能包含Bucket名称。
String objectName = "dmjxsy/demo.txt";
// 创建OSSClient实例。
OSS ossClient = new OSSClientBuilder().build(endpoint,accessKeyId,secretAccessKey);
// 填写网络流地址。
String url = "https://www.baidu.com/";
try {
InputStream inputStream = new URL(url).openStream();
// 创建PutObjectRequest对象。
PutObjectRequest putObjectRequest = new PutObjectRequest(bucketName, objectName, inputStream);
//上传字符串。
ossClient.putObject(putObjectRequest);
} 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();
}
}
}
}
1.1.3.2、执行结果
1.1.4、上传文件流
1.1.4.1、代码示例
package com.dmj.cn;
import com.aliyun.oss.ClientException;
import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClientBuilder;
import com.aliyun.oss.OSSException;
import com.aliyun.oss.common.auth.CredentialsProviderFactory;
import com.aliyun.oss.common.auth.EnvironmentVariableCredentialsProvider;
import com.aliyun.oss.internal.OSSHeaders;
import com.aliyun.oss.model.PutObjectRequest;
import com.aliyun.oss.model.StorageClass;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.InputStream;
import java.net.URL;
public class Demo {
/**
* endpoint是访问OSS的域名。
* 参考https://help.aliyun.com/zh/oss/user-guide/regions-and-endpoints?spm=a2c4g.11186623.0.0.563479cc0ioUZ7
*/
private static String endpoint = "<yourEndpoint>";
/**
* accessKeyId和accessKeySecret是OSS的访问密钥,
* 参考:https://help.aliyun.com/zh/oss/product-overview/what-is-oss?spm=a2c4g.11186623.0.i42
* 注意:accessKeyId和accessKeySecret前后都没有空格,从控制台复制时请检查并去除多余的空格。
*/
private static String accessKeyId = "<yourAccessKeyId>";
private static String accessKeySecret = "<yourAccessKeySecret>";
/**
* Bucket用来管理所存储Object的存储空间,
* 参考:https://help.aliyun.com/zh/oss/user-guide/buckets-10/?spm=a2c4g.11186623.0.0.47ba2cd9binPXN
* Bucket命名规范如下:Bucket名称在OSS范围内必须全局唯一,只能包括小写字母,数字和短横线(-),必须以小写字母或者数字开头,长度必须在3-63字节之间。
*/
private static String bucketName = "<yourBucketName>";
public static void main(String[] args) throws Exception {
// 填写Object完整路径,例如 dmjxsy/demo.txt。Object完整路径中不能包含Bucket名称。
String objectName = "dmjxsy/demo.txt";
// 创建OSSClient实例。
OSS ossClient = new OSSClientBuilder().build(endpoint,accessKeyId,secretAccessKey);
// 填写本地文件的完整路径,例如D:\\DiskId2.log。
// 如果未指定本地路径,则默认从示例程序所属项目对应本地路径中上传文件流。
String filePath= "D:\\DiskId2.log";
try {
InputStream inputStream = new FileInputStream(filePath);
// 创建PutObjectRequest对象。
PutObjectRequest putObjectRequest = new PutObjectRequest(bucketName, objectName,inputStream);
//上传字符串。
ossClient.putObject(putObjectRequest);
} 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();
}
}
}
}
1.1.4.2、执行结果
1.2、文件上传
1.2.1、代码示例
package com.dmj.cn;
import com.aliyun.oss.ClientException;
import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClientBuilder;
import com.aliyun.oss.OSSException;
import com.aliyun.oss.common.auth.CredentialsProviderFactory;
import com.aliyun.oss.common.auth.EnvironmentVariableCredentialsProvider;
import com.aliyun.oss.internal.OSSHeaders;
import com.aliyun.oss.model.PutObjectRequest;
import com.aliyun.oss.model.StorageClass;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.InputStream;
import java.net.URL;
public class Demo {
/**
* endpoint是访问OSS的域名。
* 参考https://help.aliyun.com/zh/oss/user-guide/regions-and-endpoints?spm=a2c4g.11186623.0.0.563479cc0ioUZ7
*/
private static String endpoint = "<yourEndpoint>";
/**
* accessKeyId和accessKeySecret是OSS的访问密钥,
* 参考:https://help.aliyun.com/zh/oss/product-overview/what-is-oss?spm=a2c4g.11186623.0.i42
* 注意:accessKeyId和accessKeySecret前后都没有空格,从控制台复制时请检查并去除多余的空格。
*/
private static String accessKeyId = "<yourAccessKeyId>";
private static String accessKeySecret = "<yourAccessKeySecret>";
/**
* Bucket用来管理所存储Object的存储空间,
* 参考:https://help.aliyun.com/zh/oss/user-guide/buckets-10/?spm=a2c4g.11186623.0.0.47ba2cd9binPXN
* Bucket命名规范如下:Bucket名称在OSS范围内必须全局唯一,只能包括小写字母,数字和短横线(-),必须以小写字母或者数字开头,长度必须在3-63字节之间。
*/
private static String bucketName = "<yourBucketName>";
public static void main(String[] args) throws Exception {
// 填写Object完整路径,例如 dmjxsy/file.png。Object完整路径中不能包含Bucket名称。
String objectName = "dmjxsy/file.png";
// 创建OSSClient实例。
OSS ossClient = new OSSClientBuilder().build(endpoint,accessKeyId,secretAccessKey);
// 填写本地文件的完整路径,例如D:\\file.png。
// 如果未指定本地路径,则默认从示例程序所属项目对应本地路径中上传文件流。
String filePath= "D:\\file.png";
try {
// 创建PutObjectRequest对象。
PutObjectRequest putObjectRequest = new PutObjectRequest(bucketName, objectName, new File(filePath));
//上传字符串。
ossClient.putObject(putObjectRequest);
} 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();
}
}
}
}
1.2.2、执行结果
2、表单上传
2.1、注意点
表单上传是使用HTML表单形式上传文件(Object)到指定存储空间(Bucket)中,文件最大不能超过5 GB。
2.2、代码示例
import com.aliyun.oss.common.utils.BinaryUtil;
import com.aliyun.oss.internal.OSSUtils;
import com.aliyun.oss.model.Callback;
import org.apache.commons.codec.binary.Base64;
import javax.activation.MimetypesFileTypeMap;
import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.Map;
import com.aliyun.oss.ClientException;
public class PostObjectSample {
// 填写待上传的本地文件的完整路径。
private String localFilePath = "yourLocalFile";
// Endpoint以杭州为例,其它Region请按实际情况填写。
private String endpoint = "http://oss-cn-hangzhou.aliyuncs.com";
// 阿里云账号AccessKey拥有所有API的访问权限,风险很高。强烈建议您创建并使用RAM用户进行API访问或日常运维,请登录RAM控制台创建RAM用户。
String accessKeyId = System.getenv("OSS_ACCESS_KEY_ID");
String secretAccessKey = System.getenv("OSS_ACCESS_KEY_SECRET");
// 填写Bucket名称。
private String bucketName = "yourBucketName";
// 填写不包含Bucket名称在内的Object的完整路径。
private String objectName = "yourObjectName";
// 设置回调服务器地址,例如http://oss-demo.oss-cn-hangzhou.aliyuncs.com:23450或http://127.0.0.1:9090。
private String callbackServerUrl = "yourCallbackServerUrl";
// 设置回调请求消息头中Host的值,例如oss-cn-hangzhou.aliyuncs.com。
private String callbackServerHost = "yourCallbackServerHost";
// 设置MD5值。MD5值由整个Body计算得出。
private static String contentMD5 = "yourContentMD5";
/**
* 表单上传。
* @throws Exception
*/
private void PostObject() throws Exception {
// 在URL中添加Bucket名称,添加后URL格式为http://yourBucketName.oss-cn-hangzhou.aliyuncs.com。
String urlStr = endpoint.replace("http://", "http://" + bucketName+ ".");
// 设置表单Map。
Map<String, String> formFields = new LinkedHashMap<String, String>();
// 设置文件名称。
formFields.put("key", this.objectName);
// 设置Content-Disposition。
formFields.put("Content-Disposition", "attachment;filename="
+ localFilePath);
// 设置回调参数。
// Callback callback = new Callback();
// 设置回调服务器地址,例如http://oss-demo.oss-cn-hangzhou.aliyuncs.com:23450或http://127.0.0.1:9090。
// callback.setCallbackUrl(callbackServerUrl);
// 设置回调请求消息头中Host的值,如oss-cn-hangzhou.aliyuncs.com。
// callback.setCallbackHost(callbackServerHost);
// 设置发起回调时请求Body的值。
// callback.setCallbackBody("{\\\"mimeType\\\":${mimeType},\\\"size\\\":${size}}");
// 设置发起回调请求的Content-Type。
// callback.setCalbackBodyType(Callback.CalbackBodyType.JSON);
// 设置发起回调请求的自定义参数,由Key和Value组成,Key必须以x:开始,且必须小写。
// callback.addCallbackVar("x:var1", "value1");
// callback.addCallbackVar("x:var2", "value2");
// 在表单Map中设置回调参数。
// setCallBack(formFields, callback);
// 设置OSSAccessKeyId。
formFields.put("OSSAccessKeyId", accessKeyId);
String policy = "{\"expiration\": \"2120-01-01T12:00:00.000Z\",\"conditions\": [[\"content-length-range\", 0, 104857600]]}";
String encodePolicy = new String(Base64.encodeBase64(policy.getBytes()));
// 设置policy。
formFields.put("policy", encodePolicy);
// 生成签名。
String signaturecom = com.aliyun.oss.common.auth.ServiceSignature.create().computeSignature(accessKeySecret, encodePolicy);
// 设置签名。
formFields.put("Signature", signaturecom);
String ret = formUpload(urlStr, formFields, localFilePath);
System.out.println("Post Object [" + this.objectName + "] to bucket [" + bucketName + "]");
System.out.println("post reponse:" + ret);
}
private static String formUpload(String urlStr, Map<String, String> formFields, String localFile)
throws Exception {
String res = "";
HttpURLConnection conn = null;
String boundary = "9431149156168";
try {
URL url = new URL(urlStr);
conn = (HttpURLConnection) url.openConnection();
conn.setConnectTimeout(5000);
conn.setReadTimeout(30000);
conn.setDoOutput(true);
conn.setDoInput(true);
conn.setRequestMethod("POST");
conn.setRequestProperty("User-Agent",
"Mozilla/5.0 (Windows; U; Windows NT 6.1; zh-CN; rv:1.9.2.6)");
// 设置MD5值。MD5值由整个Body计算得出。如果希望开启MD5校验,可参考MD5加密设置。
// conn.setRequestProperty("Content-MD5", contentMD5);
conn.setRequestProperty("Content-Type",
"multipart/form-data; boundary=" + boundary);
OutputStream out = new DataOutputStream(conn.getOutputStream());
// 遍历读取表单Map中的数据,将数据写入到输出流中。
if (formFields != null) {
StringBuffer strBuf = new StringBuffer();
Iterator<Map.Entry<String, String>> iter = formFields.entrySet().iterator();
int i = 0;
while (iter.hasNext()) {
Map.Entry<String, String> entry = iter.next();
String inputName = entry.getKey();
String inputValue = entry.getValue();
if (inputValue == null) {
continue;
}
if (i == 0) {
strBuf.append("--").append(boundary).append("\r\n");
strBuf.append("Content-Disposition: form-data; name=\""
+ inputName + "\"\r\n\r\n");
strBuf.append(inputValue);
} else {
strBuf.append("\r\n").append("--").append(boundary).append("\r\n");
strBuf.append("Content-Disposition: form-data; name=\""
+ inputName + "\"\r\n\r\n");
strBuf.append(inputValue);
}
i++;
}
out.write(strBuf.toString().getBytes());
}
// 读取文件信息,将要上传的文件写入到输出流中。
File file = new File(localFile);
String filename = file.getName();
String contentType = new MimetypesFileTypeMap().getContentType(file);
if (contentType == null || contentType.equals("")) {
contentType = "application/octet-stream";
}
StringBuffer strBuf = new StringBuffer();
strBuf.append("\r\n").append("--").append(boundary)
.append("\r\n");
strBuf.append("Content-Disposition: form-data; name=\"file\"; "
+ "filename=\"" + filename + "\"\r\n");
strBuf.append("Content-Type: " + contentType + "\r\n\r\n");
out.write(strBuf.toString().getBytes());
DataInputStream in = new DataInputStream(new FileInputStream(file));
int bytes = 0;
byte[] bufferOut = new byte[1024];
while ((bytes = in.read(bufferOut)) != -1) {
out.write(bufferOut, 0, bytes);
}
in.close();
byte[] endData = ("\r\n--" + boundary + "--\r\n").getBytes();
out.write(endData);
out.flush();
out.close();
// 读取返回数据。
strBuf = new StringBuffer();
BufferedReader reader = new BufferedReader(new InputStreamReader(conn.getInputStream()));
String line = null;
while ((line = reader.readLine()) != null) {
strBuf.append(line).append("\n");
}
res = strBuf.toString();
reader.close();
reader = null;
} catch (ClientException e) {
System.err.println("Send post request exception: " + e);
System.err.println(e.getErrorCode()+" msg="+e.getMessage());
throw e;
} finally {
if (conn != null) {
conn.disconnect();
conn = null;
}
}
return res;
}
private static void setCallBack(Map<String, String> formFields, Callback callback) {
if (callback != null) {
String jsonCb = OSSUtils.jsonizeCallback(callback);
String base64Cb = BinaryUtil.toBase64String(jsonCb.getBytes());
formFields.put("callback", base64Cb);
if (callback.hasCallbackVar()) {
Map<String, String> varMap = callback.getCallbackVar();
for (Map.Entry<String, String> entry : varMap.entrySet()) {
formFields.put(entry.getKey(), entry.getValue());
}
}
}
}
public static void main(String[] args) throws Exception {
PostObjectSample ossPostObject = new PostObjectSample();
ossPostObject.PostObject();
}
}
3、追加上传
3.1、注意点
追加上传是指通过AppendObject方法在已上传的追加类型文件(Appendable Object)末尾直接追加内容,最大不能超过5GB。
- 当文件不存在时,调用AppendObject接口会创建一个追加类型文件。
- 当文件已存在时:
-
- 如果文件为追加类型文件,且设置的追加位置和文件当前长度相等,则直接在该文件末尾追加内容。
-
- 如果文件为追加类型文件,但是设置的追加位置和文件当前长度不相等,则抛出PositionNotEqualToLength异常。
-
- 如果文件为非追加类型文件时,例如通过简单上传的文件类型为Normal的文件,则抛出ObjectNotAppendable异常。
- 追加类型文件暂不支持CopyObject操作。
3.2、代码示例
import com.aliyun.oss.ClientException;
import com.aliyun.oss.OSS;
import com.aliyun.oss.common.auth.*;
import com.aliyun.oss.OSSClientBuilder;
import com.aliyun.oss.OSSException;
import com.aliyun.oss.model.AppendObjectRequest;
import com.aliyun.oss.model.AppendObjectResult;
import com.aliyun.oss.model.ObjectMetadata;
import java.io.ByteArrayInputStream;
public class Demo {
public static void main(String[] args) throws Exception {
// Endpoint以华东1(杭州)为例,其它Region请按实际情况填写。
String endpoint = "https://oss-cn-hangzhou.aliyuncs.com";
// 从环境变量中获取访问凭证。运行本代码示例之前,请确保已设置环境变量OSS_ACCESS_KEY_ID和OSS_ACCESS_KEY_SECRET。
EnvironmentVariableCredentialsProvider credentialsProvider = CredentialsProviderFactory.newEnvironmentVariableCredentialsProvider();
// 填写Bucket名称,例如examplebucket。
String bucketName = "examplebucket";
// 填写Object完整路径,完整路径中不能包含Bucket名称,例如exampledir/exampleobject.txt。
String objectName = "exampledir/exampleobject.txt";
String content1 = "Hello OSS A \n";
String content2 = "Hello OSS B \n";
String content3 = "Hello OSS C \n";
// 创建OSSClient实例。
OSS ossClient = new OSSClientBuilder().build(endpoint, credentialsProvider);
try {
ObjectMetadata meta = new ObjectMetadata();
// 指定上传的内容类型。
meta.setContentType("text/plain");
// 指定该Object的网页缓存行为。
//meta.setCacheControl("no-cache");
// 指定该Object被下载时的名称。
//meta.setContentDisposition("attachment;filename=oss_download.txt");
// 指定该Object的内容编码格式。
//meta.setContentEncoding(OSSConstants.DEFAULT_CHARSET_NAME);
// 该请求头用于检查消息内容是否与发送时一致。
//meta.setContentMD5("ohhnqLBJFiKkPSBO1eNaUA==");
// 指定过期时间。
//try {
// meta.setExpirationTime(DateUtil.parseRfc822Date("Wed, 08 Jul 2022 16:57:01 GMT"));
//} catch (ParseException e) {
// e.printStackTrace();
//}
// 指定服务器端加密方式。此处指定为OSS完全托管密钥进行加密(SSE-OSS)。
//meta.setServerSideEncryption(ObjectMetadata.AES_256_SERVER_SIDE_ENCRYPTION);
// 指定Object的访问权限。此处指定为私有访问权限。
//meta.setObjectAcl(CannedAccessControlList.Private);
// 指定Object的存储类型。
//meta.setHeader(OSSHeaders.OSS_STORAGE_CLASS, StorageClass.Standard);
// 创建AppendObject时可以添加x-oss-meta-*,继续追加时不可以携带此参数。如果配置以x-oss-meta-*为前缀的参数,则该参数视为元数据。
//meta.setHeader("x-oss-meta-author", "Alice");
// 通过AppendObjectRequest设置多个参数。
AppendObjectRequest appendObjectRequest = new AppendObjectRequest(bucketName, objectName, new ByteArrayInputStream(content1.getBytes()),meta);
// 通过AppendObjectRequest设置单个参数。
// 设置Bucket名称。
//appendObjectRequest.setBucketName(bucketName);
// 设置Object名称。
//appendObjectRequest.setKey(objectName);
// 设置待追加的内容。可选类型包括InputStream类型和File类型。此处为InputStream类型。
//appendObjectRequest.setInputStream(new ByteArrayInputStream(content1.getBytes()));
// 设置待追加的内容。可选类型包括InputStream类型和File类型。此处为File类型。
//appendObjectRequest.setFile(new File("D:\\localpath\\examplefile.txt"));
// 指定文件的元信息,第一次追加时有效。
//appendObjectRequest.setMetadata(meta);
// 第一次追加。
// 设置文件的追加位置。
appendObjectRequest.setPosition(0L);
AppendObjectResult appendObjectResult = ossClient.appendObject(appendObjectRequest);
// 文件的64位CRC值。此值根据ECMA-182标准计算得出。
System.out.println(appendObjectResult.getObjectCRC());
// 第二次追加。
// nextPosition表示下一次请求中应当提供的Position,即文件当前的长度。
appendObjectRequest.setPosition(appendObjectResult.getNextPosition());
appendObjectRequest.setInputStream(new ByteArrayInputStream(content2.getBytes()));
appendObjectResult = ossClient.appendObject(appendObjectRequest);
// 第三次追加。
appendObjectRequest.setPosition(appendObjectResult.getNextPosition());
appendObjectRequest.setInputStream(new ByteArrayInputStream(content3.getBytes()));
appendObjectResult = ossClient.appendObject(appendObjectRequest);
} 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();
}
}
}
}
4、断点续传上传
4.1、注意点
通过断点续传上传的方式将文件上传到OSS前,您可以指定断点记录点。上传过程中,如果出现网络异常或程序崩溃导致文件上传失败时,将从断点记录处继续上传未上传完成的部分。最大不能超过48.8TB。
4.2、代码示例
import com.aliyun.oss.OSS;
import com.aliyun.oss.common.auth.*;
import com.aliyun.oss.OSSClientBuilder;
import com.aliyun.oss.OSSException;
import com.aliyun.oss.model.*;
public class Demo {
public static void main(String[] args) {
// Endpoint以华东1(杭州)为例,其它Region请按实际情况填写。
String endpoint = "https://oss-cn-hangzhou.aliyuncs.com";
// 阿里云账号AccessKey拥有所有API的访问权限,风险很高。强烈建议您创建并使用RAM用户进行API访问或日常运维,请登录RAM控制台创建RAM用户。
String accessKeyId = "yourAccessKeyId";
String accessKeySecret = "yourAccessKeySecret";
// 创建OSSClient实例。
OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);
try {
ObjectMetadata meta = new ObjectMetadata();
// 指定上传的内容类型。
meta.setContentType("text/plain");
// 文件上传时设置访问权限ACL。
// meta.setObjectAcl(CannedAccessControlList.Private);
// 通过UploadFileRequest设置多个参数。
// 依次填写Bucket名称(例如examplebucket)以及Object完整路径(例如exampledir/exampleobject.txt),Object完整路径中不能包含Bucket名称。
UploadFileRequest uploadFileRequest = new UploadFileRequest("examplebucket","exampledir/exampleobject.txt");
// 通过UploadFileRequest设置单个参数。
// 填写本地文件的完整路径,例如D:\\localpath\\examplefile.txt。如果未指定本地路径,则默认从示例程序所属项目对应本地路径中上传文件。
uploadFileRequest.setUploadFile("D:\\localpath\\examplefile.txt");
// 指定上传并发线程数,默认值为1。
uploadFileRequest.setTaskNum(5);
// 指定上传的分片大小,单位为字节,取值范围为100 KB~5 GB。默认值为100 KB。
uploadFileRequest.setPartSize(1 * 1024 * 1024);
// 开启断点续传,默认关闭。
uploadFileRequest.setEnableCheckpoint(true);
// 记录本地分片上传结果的文件。上传过程中的进度信息会保存在该文件中,如果某一分片上传失败,再次上传时会根据文件中记录的点继续上传。上传完成后,该文件会被删除。
// 如果未设置该值,默认与待上传的本地文件同路径,名称为${uploadFile}.ucp。
uploadFileRequest.setCheckpointFile("yourCheckpointFile");
// 文件的元数据。
uploadFileRequest.setObjectMetadata(meta);
// 设置上传回调,参数为Callback类型。
//uploadFileRequest.setCallback("yourCallbackEvent");
// 断点续传上传。
ossClient.uploadFile(uploadFileRequest);
} 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 (Throwable 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 {
// 关闭OSSClient。
if (ossClient != null) {
ossClient.shutdown();
}
}
}
}
5、分片上传
5.1、注意点
OSS提供的分片上传(Multipart Upload)功能,将要上传的较大文件(Object)分成多个分片(Part)来分别上传,上传完成后再调用CompleteMultipartUpload接口将这些Part组合成一个Object来达到断点续传的效果。最大不能超过48.8TB。
5.2、使用场景
- 大文件加速上传
-
- 当文件大小超过5 GB时,使用分片上传可实现并行上传多个Part以加快上传速度。
- 网络环境较差
-
- 网络环境较差时,建议使用分片上传。当出现上传失败的时候,您仅需重传失败的Part。
- 文件大小不确定
-
- 可以在需要上传的文件大小还不确定的情况下开始上传,这种场景在视频监控等行业应用中比较常见。
5.3、流程图
5.4、使用限制
项目 | 规格 |
---|---|
文件大小 | 不超过48.8 TB |
Part数量 | 1~10, 000个 |
单个Part大小 | 最小值为100 KB,最大值为5 GB。最后一个Part的大小不要求大于100 KB |
单次ListParts请求返回的Part最大数量 | 1, 000个 |
单次ListMultipartUploads请求返回的Multipart Upload事件最大数量 | 1, 000个 |
5.5、代码示例
import com.aliyun.oss.ClientException;
import com.aliyun.oss.OSS;
import com.aliyun.oss.common.auth.*;
import com.aliyun.oss.OSSClientBuilder;
import com.aliyun.oss.OSSException;
import com.aliyun.oss.internal.Mimetypes;
import com.aliyun.oss.model.*;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
public class Demo {
public static void main(String[] args) throws Exception {
// Endpoint以华东1(杭州)为例,其它Region请按实际情况填写。
String endpoint = "https://oss-cn-hangzhou.aliyuncs.com";
// 从环境变量中获取访问凭证。运行本代码示例之前,请确保已设置环境变量OSS_ACCESS_KEY_ID和OSS_ACCESS_KEY_SECRET。
EnvironmentVariableCredentialsProvider credentialsProvider = CredentialsProviderFactory.newEnvironmentVariableCredentialsProvider();
// 填写Bucket名称,例如examplebucket。
String bucketName = "examplebucket";
// 填写Object完整路径,例如exampledir/exampleobject.txt。Object完整路径中不能包含Bucket名称。
String objectName = "exampledir/exampleobject.txt";
// 待上传本地文件路径。
String filePath = "D:\\localpath\\examplefile.txt";
// 创建OSSClient实例。
OSS ossClient = new OSSClientBuilder().build(endpoint, credentialsProvider);
try {
// 创建InitiateMultipartUploadRequest对象。
InitiateMultipartUploadRequest request = new InitiateMultipartUploadRequest(bucketName, objectName);
// 如果需要在初始化分片时设置请求头,请参考以下示例代码。
ObjectMetadata metadata = new ObjectMetadata();
// metadata.setHeader(OSSHeaders.OSS_STORAGE_CLASS, StorageClass.Standard.toString());
// 指定该Object的网页缓存行为。
// metadata.setCacheControl("no-cache");
// 指定该Object被下载时的名称。
// metadata.setContentDisposition("attachment;filename=oss_MultipartUpload.txt");
// 指定该Object的内容编码格式。
// metadata.setContentEncoding(OSSConstants.DEFAULT_CHARSET_NAME);
// 指定初始化分片上传时是否覆盖同名Object。此处设置为true,表示禁止覆盖同名Object。
// metadata.setHeader("x-oss-forbid-overwrite", "true");
// 指定上传该Object的每个part时使用的服务器端加密方式。
// metadata.setHeader(OSSHeaders.OSS_SERVER_SIDE_ENCRYPTION, ObjectMetadata.KMS_SERVER_SIDE_ENCRYPTION);
// 指定Object的加密算法。如果未指定此选项,表明Object使用AES256加密算法。
// metadata.setHeader(OSSHeaders.OSS_SERVER_SIDE_DATA_ENCRYPTION, ObjectMetadata.KMS_SERVER_SIDE_ENCRYPTION);
// 指定KMS托管的用户主密钥。
// metadata.setHeader(OSSHeaders.OSS_SERVER_SIDE_ENCRYPTION_KEY_ID, "9468da86-3509-4f8d-a61e-6eab1eac****");
// 指定Object的存储类型。
// metadata.setHeader(OSSHeaders.OSS_STORAGE_CLASS, StorageClass.Standard);
// 指定Object的对象标签,可同时设置多个标签。
// metadata.setHeader(OSSHeaders.OSS_TAGGING, "a:1");
// request.setObjectMetadata(metadata);
// 根据文件自动设置ContentType。如果不设置,ContentType默认值为application/oct-srream。
if (metadata.getContentType() == null) {
metadata.setContentType(Mimetypes.getInstance().getMimetype(new File(filePath), 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。
// 根据上传的数据大小计算分片数。以本地文件为例,说明如何通过File.length()获取上传数据的大小。
final File sampleFile = new File(filePath);
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;
UploadPartRequest uploadPartRequest = new UploadPartRequest();
uploadPartRequest.setBucketName(bucketName);
uploadPartRequest.setKey(objectName);
uploadPartRequest.setUploadId(uploadId);
// 设置上传的分片流。
// 以本地文件为例说明如何创建FIleInputstream,并通过InputStream.skip()方法跳过指定数据。
InputStream instream = new FileInputStream(sampleFile);
instream.skip(startPos);
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);
// 如果需要在完成分片上传的同时设置文件访问权限,请参考以下示例代码。
// completeMultipartUploadRequest.setObjectACL(CannedAccessControlList.Private);
// 指定是否列举当前UploadId已上传的所有Part。仅在Java SDK为3.14.0及以上版本时,支持通过服务端List分片数据来合并完整文件时,将CompleteMultipartUploadRequest中的partETags设置为null。
// Map<String, String> headers = new HashMap<String, String>();
// 如果指定了x-oss-complete-all:yes,则OSS会列举当前UploadId已上传的所有Part,然后按照PartNumber的序号排序并执行CompleteMultipartUpload操作。
// 如果指定了x-oss-complete-all:yes,则不允许继续指定body,否则报错。
// headers.put("x-oss-complete-all","yes");
// completeMultipartUploadRequest.setHeaders(headers);
// 完成分片上传。
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();
}
}
}
}