阿里oss视频 分片上传

pom.xml配置


      com.aliyun.oss
      aliyun-sdk-oss
      3.8.1 
 
 
如果引入oss 与 net.sf.jso冲突 ,可添加以下代码:

      net.sf.json-lib
       json-lib
       2.4
       jdk15
 

逻辑代码

public ResultVM uploadVideo(HttpServletRequest request) throws Exception {
        MultipartHttpServletRequest multiRequest = (MultipartHttpServletRequest) request;
        MultipartFile file = multiRequest.getFile("file");
        java.io.File sampleFile = ImageWordsUtil.fileToMultipartFile(file);
        String filePath =  "video" + "/";
        if (file != null) {
            //单个文件最大
            String fileName = ossService.genFileNameByUserId(filePath, file.getOriginalFilename());
            Map map = new HashMap<>();
            map.put("noDomainUrls", ossProperties.getDomainName() + fileName);
            log.info("url为" + ossProperties.getDomainName() + fileName);
            new Thread(new Runnable() {
                @Override
                public void run() {
                    try {
                        ossMultipartUploadService.uploadVideo(sampleFile,fileName);
                    }catch (Exception e){
                        e.getMessage();
                    }

                 }
            }).start();
            log.info("url为输出" + ossProperties.getDomainName() + fileName);
            return ResultVMUtil.success(map);
        } else {
            log.warn("上传文件为空");
            return ResultVMUtil.error(ResultEnum.UPLOAD_FILE_IS_NULL);
        }
    }

public static File fileToMultipartFile(MultipartFile multipartFile)throws IOException {

        String fileName = multipartFile.getOriginalFilename();
        String fileEndName = fileName.substring(fileName.lastIndexOf("."));

        String result= DateUtil.getDateFormatterStr();
        Path path = Paths.get( fileName.substring(0,fileName.indexOf("."))+"-"+  result + fileEndName);

        byte[] bytes = multipartFile.getBytes();
        // 文件写入指定路径
        Files.write(path, bytes);
        File file = new File(path.toString());
        return  file;

    }
import com.aliyun.oss.*;
import com.aliyun.oss.model.*;
import com.ysx.zzedu.common.config.OssProperties;
import com.ysx.zzedu.common.utils.DateUtil;
import com.ysx.zzedu.common.utils.ImageWordsUtil;
import com.ysx.zzedu.service.IUserService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.io.*;
import java.util.*;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;


/**
 * @author
 * @version 1.0 
 * @info oss上传文件
 * @since 1.0
 */
@Slf4j
@Service
public class OssMultipartUploadService {

    @Autowired
    private OssProperties ossProperties;

    private OSS client = null;

    //表示上传文件到OSS时需要指定包含文件后缀在内的完整路径,例如abc/efg/123.jpg
    private String objectName = "";

 	// 定长线程池
    private ExecutorService executorService = Executors.newFixedThreadPool(5);
    private static  List partETags = null;
    private static final int partSize = 5 * 1024 * 1024;   // 5MB 分片大小

    public String uploadVideo(File sampleFile,String localPath){
        String endPoint = ossProperties.getEndPoint();
        String accessKeyId = ossProperties.getAccessKeyId();
        String accessKeySecret = ossProperties.getAccessKeySecret();
        String bucketName = ossProperties.getBucketName();

        long start = System.currentTimeMillis();
        objectName = localPath;
        ClientBuilderConfiguration conf = new ClientBuilderConfiguration();
        conf.setIdleConnectionTime(5000);
        client = new OSSClientBuilder().build(endPoint, accessKeyId,accessKeySecret,conf);

        String fileUrl = null;
        try {
            String uploadId = claimUploadId();
            log.info("申请一个新的上传id:" + uploadId);
          
            // 文件大小
            long fileLength = sampleFile.length();
            // 分片总数(总共分几个部分)
            int partCount = (int) (fileLength / partSize);
            if (fileLength % partSize != 0) {
                partCount++;
            }
            if (partCount > 10000) {
                log.warn("partCount总数不应超过10000");
                return null;
            } else {
                log.info("文件总共分片数:" + partCount);
            }
            partETags = Collections.synchronizedList(new ArrayList(partCount));
            CountDownLatch latch = new CountDownLatch(partCount);
            log.info("***************开始准备上传************");
            for (int i = 0; i < partCount; i++) {
                long startPos = i * partSize;
                long curPartSize = (i + 1 == partCount) ? (fileLength - startPos) : partSize;
                executorService.execute(new PartUploader(sampleFile, startPos, curPartSize, i + 1, uploadId, latch));
            }
            latch.await();
            if (partETags.size() != partCount) {
                StringBuilder partETagsStr = new StringBuilder("(");
                for (PartETag item : partETags) {
                    partETagsStr.append(item.getPartNumber()).append(",");
                }
                partETagsStr.append(")");
                log.info(String.format("partCount:%s*******,partEtages:%s*******,partETagsSize:%s", partCount, partETagsStr, partETags.size()));
                throw new IllegalStateException("上传多个部分失败,因为有些部分还没有完成");
            } else {
                log.info("成功地将多个部分合并上传到一个名为的对象中 " + objectName);
            }
            listAllParts(uploadId);
            completeMultipartUpload(uploadId);
            log.info("获取一个对象");
            long end = System.currentTimeMillis();
            // 生成文件地址
//            client.getObject(new GetObjectRequest(bucketName, key), new File(localFilePath));
            boolean isFileExist = client.doesObjectExist(bucketName, objectName);
            if (isFileExist) {
                fileUrl = ossProperties.getDomainName() + objectName;
                log.info(String.format("上传成功*****耗时:%s*****,文件地址:%s",((end - start) / 1000),fileUrl));
            } else {
                throw new Exception("上传失败,文件不存在");
            }
        } catch (OSSException oe) {
            log.error(oe.getMessage(), oe);
        } catch (ClientException ce) {
            log.error(ce.getErrorMessage(), ce);
        } catch (Exception e) {
            log.error(e.getMessage(), e);
        } finally {
            if (client != null) {
                client.shutdown();
            }
            if (sampleFile != null) {
                sampleFile.delete();
            }
            partETags.clear();
            partETags = null;
            return fileUrl;
        }
        
    }
    private class PartUploader implements Runnable {

        private File localFile;
        private long startPos;

        private long partSize;
        private int partNumber;
        private String uploadId;
        private CountDownLatch latch;

        public PartUploader(File localFile, long startPos, long partSize, int partNumber, String uploadId,CountDownLatch latch) {
            this.localFile = localFile;
            this.startPos = startPos;
            this.partSize = partSize;
            this.partNumber = partNumber;
            this.uploadId = uploadId;
            this.latch = latch;
        }

        @Override
        public void run() {
            InputStream instream = null;
            try {
                instream = new FileInputStream(this.localFile);
                instream.skip(this.startPos);

                UploadPartRequest uploadPartRequest = new UploadPartRequest();
                uploadPartRequest.setBucketName(ossProperties.getBucketName());
                uploadPartRequest.setKey(objectName);
                uploadPartRequest.setUploadId(this.uploadId);
                uploadPartRequest.setInputStream(instream);
                uploadPartRequest.setPartSize(this.partSize);
                uploadPartRequest.setPartNumber(this.partNumber);

                UploadPartResult uploadPartResult = client.uploadPart(uploadPartRequest);
                System.out.println("Part#" + this.partNumber + " 完成\n");
                synchronized (partETags) {
                    partETags.add(uploadPartResult.getPartETag());
                }
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                if (instream != null) {
                    try {
                        instream.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
                latch.countDown();
            }
        }
    }

    private  File createSampleFile() throws IOException {
        File file = File.createTempFile("oss-java-sdk-", ".txt");
        file.deleteOnExit();

        Writer writer = new OutputStreamWriter(new FileOutputStream(file));
        for (int i = 0; i < 1000000; i++) {
            writer.write("abcdefghijklmnopqrstuvwxyz\n");
            writer.write("0123456789011234567890\n");
        }
        writer.close();

        return file;
    }

    private String claimUploadId() {
        // 创建InitiateMultipartUploadRequest对象。
        InitiateMultipartUploadRequest request = new InitiateMultipartUploadRequest(ossProperties.getBucketName(), objectName);
        InitiateMultipartUploadResult result = client.initiateMultipartUpload(request);
        return result.getUploadId();
    }

    private void completeMultipartUpload(String uploadId) {
        // Make part numbers in ascending order
        Collections.sort(partETags, new Comparator() {

            @Override
            public int compare(PartETag p1, PartETag p2) {
                return p1.getPartNumber() - p2.getPartNumber();
            }
        });

        System.out.println("Completing to upload multiparts\n");
        // 创建CompleteMultipartUploadRequest对象。
// 在执行完成分片上传操作时,需要提供所有有效的partETags。OSS收到提交的partETags后,会逐一验证每个分片的有效性。当所有的数据分片验证通过后,OSS将把这些分片组合成一个完整的文件。
        CompleteMultipartUploadRequest completeMultipartUploadRequest =
                new CompleteMultipartUploadRequest(ossProperties.getBucketName(), objectName, uploadId, partETags);
        client.completeMultipartUpload(completeMultipartUploadRequest);
    }

    private void listAllParts(String uploadId) {
        System.out.println("Listing all parts......");
        ListPartsRequest listPartsRequest = new ListPartsRequest(ossProperties.getBucketName(), objectName, uploadId);
        PartListing partListing = client.listParts(listPartsRequest);

        int partCount = partListing.getParts().size();
        for (int i = 0; i < partCount; i++) {
            PartSummary partSummary = partListing.getParts().get(i);
            System.out.println("\tPart#" + partSummary.getPartNumber() + ", ETag=" + partSummary.getETag());
        }
        System.out.println();
    }
}

你可能感兴趣的:(阿里oss视频 分片上传)