阿里oss视频 分片上传

pom.xml配置

<dependency>
      <groupId>com.aliyun.oss</groupId>
      <artifactId>aliyun-sdk-oss</artifactId>
      <version>3.8.1</version> 
 </dependency>
 
如果引入oss 与 net.sf.jso冲突 ,可添加以下代码:
<dependency>
      <groupId>net.sf.json-lib</groupId>
       <artifactId>json-lib</artifactId>
       <version>2.4</version>
       <classifier>jdk15</classifier>
 </dependency>

逻辑代码

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<String, Object> 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<PartETag> 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<PartETag>(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<PartETag>() {

            @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();
    }
}

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
你可以使用 Element UI 和阿里云 OSS 来实现分片视频。首先,你需要在你的项目中引入 Element UI 组件库和阿里云 OSS 的 SDK。 然后,你可以使用 Element UI 中的上组件来实现文件选择和上的功能。在上组件中,你可以设置一些参数来启用分片功能。例如,你可以设置 `chunkSize` 参数来指定每个分片的大小,以及 `chunkRetry` 参数来设置分片失败时的重试次数。 在上过程中,你可以使用阿里云 OSS 的 SDK 来进行分片。你需要将视频文件切割成多个分片,并将每个分片到阿里云 OSS 中的指定位置。可以使用 `oss.multipartUpload` 方法来实现分片功能。 具体的代码实现步骤如下: 1. 引入 Element UI 和阿里云 OSS 的 SDK: ```javascript import ElementUI from 'element-ui'; import 'element-ui/lib/theme-chalk/index.css'; import OSS from 'ali-oss'; ``` 2. 初始化阿里云 OSS 客户端: ```javascript const client = new OSS({ region: 'your_region', accessKeyId: 'your_access_key_id', accessKeySecret: 'your_access_key_secret', bucket: 'your_bucket_name' }); ``` 3. 在上组件中设置分片参数: ```html <el-upload :action="your_upload_url" :on-success="handleSuccess" :chunk-size="your_chunk_size" :chunk-retry="your_chunk_retry" > <el-button slot="trigger">选择视频文件</el-button> </el-upload> ``` 4. 实现上成功的回调函数: ```javascript handleSuccess(response, file, fileList) { // 在上成功后,你可以根据需要进行后续处理,例如保存视频路径等操作 } ``` 5. 在回调函数中实现分片: ```javascript handleSuccess(response, file, fileList) { const { uploadId, name } = response.data; // 获取上 ID 和文件名 const chunks = splitVideoIntoChunks(file); // 将视频文件切割成多个分片 const uploadPromises = chunks.map((chunk, index) => { return client.uploadPart(name, uploadId, index + 1, chunk); // 上每个分片 }); Promise.all(uploadPromises) .then(results => { const etags = results.map(result => result.etag); return client.completeMultipartUpload(name, uploadId, etags); // 完成分片 }) .then(() => { console.log('分片完成'); }) .catch(error => { console.error('分片失败', error); }); } ``` 以上是一个简单的示例,你可以根据自己的需求进行适当调整。希望以上信息对你有所帮助!

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值