OSS分段上传

import com.aliyun.oss.ClientConfiguration;
import com.aliyun.oss.ClientException;
import com.aliyun.oss.OSSClient;
import com.aliyun.oss.OSSException;
import com.aliyun.oss.model.*;
import com.xw.cn.jujiaoweb.utils.UUIDUtil;
import org.springframework.web.multipart.MultipartFile;

import java.io.InputStream;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

public class OSSMultipartUploadUtil {

    private static final String ACCESS_ID = "***********************************";
    private static final String ACCESS_KEY = "***********************************";
    private static final String OSS_ENDPOINT = "***********************************";
    private static final long PART_SIZE = 5 * 1024 * 1024L; // 每个Part的大小,最小为5MB
    private static final int CONCURRENCIES = 2; // 上传Part的并发线程数。
    private static final String partUrl = "***********************************";

    private static String bucketName = "*****"; // 需要存储的bucketName
    private static String picLocation = "bigFile/"; // 图片保存路径
    /**
     * 分段上传大文件,通过Multipart的方式上传一个大文件,要上传文件的大小必须大于一个Part允许的最小大小,即5MB。
     * @throws OSSException
     * @throws ClientException
     * @throws InterruptedException
     */
    public static String uploadBigFile(MultipartFile file, String fileTypeName) throws OSSException, ClientException, InterruptedException {
        long begin = System.currentTimeMillis();
        ClientConfiguration config = new ClientConfiguration();
        OSSClient client = new OSSClient(OSS_ENDPOINT, ACCESS_ID, ACCESS_KEY, config);
        String key = String.format("%s%s.%s",picLocation,UUIDUtil.getUUID(),fileTypeName);
        int partCount = calPartCount(file.getSize());
        if (partCount <= 1) {
            throw new IllegalArgumentException("要上传文件的大小必须大于一个Part的字节数:" + PART_SIZE);
        }
        String uploadId = initMultipartUpload(client,bucketName, key);
        ExecutorService pool = Executors.newFixedThreadPool(CONCURRENCIES);
        List<PartETag> eTags = Collections.synchronizedList(new ArrayList<PartETag>());

        for (int i = 0; i < partCount; i++) {
            long start = PART_SIZE * i;
            long curPartSize = PART_SIZE < file.getSize() - start ? PART_SIZE : file.getSize() - start;
            pool.execute(new UploadPartThread(client,bucketName, key,file, uploadId, i + 1, PART_SIZE * i, curPartSize,eTags));
        }
        pool.shutdown();
        while (!pool.isTerminated()) {
            pool.awaitTermination(5, TimeUnit.SECONDS);
        }
        if (eTags.size() != partCount) {
            throw new IllegalStateException("Multipart上传失败,有Part未上传成功。");
        }
        completeMultipartUpload(client,bucketName, key, uploadId, eTags);
        String fileUrl = String.format("%s%s",partUrl,key);
        long end = System.currentTimeMillis();
        System.out.println(end - begin);
        return fileUrl;
    }

    // 根据文件的大小和每个Part的大小计算需要划分的Part个数。
    private static int calPartCount(long length) {
        int partCount = (int) (length / PART_SIZE);
        if (length % PART_SIZE != 0) {
            partCount++;
        }
        return partCount;
    }

    // 初始化一个Multi-part upload请求。
    private static String initMultipartUpload(OSSClient client,String bucketName, String key) throws OSSException, ClientException {
        InitiateMultipartUploadRequest initUploadRequest = new InitiateMultipartUploadRequest(bucketName, key);
        InitiateMultipartUploadResult initResult = client.initiateMultipartUpload(initUploadRequest);
        String uploadId = initResult.getUploadId();
        return uploadId;
    }

    // 完成一个multi-part请求。
    private static void completeMultipartUpload(OSSClient client,String bucketName, String key, String uploadId, List<PartETag> eTags) throws OSSException, ClientException {
        // 为part按partnumber排序
        Collections.sort(eTags, new Comparator<PartETag>() {
            public int compare(PartETag arg0, PartETag arg1) {
                PartETag part1 = arg0;
                PartETag part2 = arg1;
                return part1.getPartNumber() - part2.getPartNumber();
            }
        });
        CompleteMultipartUploadRequest completeMultipartUploadRequest = new CompleteMultipartUploadRequest(bucketName, key, uploadId, eTags);
        client.completeMultipartUpload(completeMultipartUploadRequest);
    }

    private static class UploadPartThread implements Runnable {
        private MultipartFile file;
        private String bucket;
        private String object;
        private long start;
        private long size;
        private List<PartETag> eTags;
        private int partId;
        private OSSClient client;
        private String uploadId;

        UploadPartThread(OSSClient client,String bucket, String object,MultipartFile file, String uploadId, int partId, long start,long partSize, List<PartETag> eTags) {
            this.file = file;
            this.bucket = bucket;
            this.object = object;
            this.start = start;
            this.size = partSize;
            this.eTags = eTags;
            this.partId = partId;
            this.client = client;
            this.uploadId = uploadId;
        }

        @Override
        public void run() {
            InputStream in = null;
            try {
                in = file.getInputStream();
                in.skip(start);

                UploadPartRequest uploadPartRequest = new UploadPartRequest();
                uploadPartRequest.setBucketName(bucket);
                uploadPartRequest.setKey(object);
                uploadPartRequest.setUploadId(uploadId);
                uploadPartRequest.setInputStream(in);
                uploadPartRequest.setPartSize(size);
                uploadPartRequest.setPartNumber(partId);

                UploadPartResult uploadPartResult = client.uploadPart(uploadPartRequest);
                eTags.add(uploadPartResult.getPartETag());
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                if (in != null)
                    try {
                        in.close();
                    } catch (Exception e) {
                    }
            }
        }
    }
}

猜你喜欢

转载自blog.csdn.net/u013045878/article/details/81103400