阿里云OSS文件上传下载【专栏】------文件上传(一)


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();
            }
        }
    }
}
  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值