阿里云视频点播服务流式上传返回前端进度条

该博客介绍了如何在前后端分离的项目中,利用阿里云视频点播服务的流式上传功能,并结合Redis实现视频上传进度的实时反馈。主要步骤包括:在回调方法中更新Redis中的进度数据,前端通过接口轮询获取进度。代码示例展示了控制器、业务实现层和上传进度回调方法类的实现。
摘要由CSDN通过智能技术生成

提示:前后端分离项目,流式上传到视频点播服务获取实时上传进度

阿里云视频点播服务流式上传返回前端进度条


实现思路:在阿里云的回调方法中,将上传的进度实时存入redis服务器中,然后前端在视频上传的时候重复请求获取视频上传进度的接口

话不多说:直接上代码

控制层

package com.ruiya.vod.controller;

import com.ruiya.commons.utils.R;
import com.ruiya.vod.service.VodService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

/**
 * description:阿里云视频点播服务控制层
 * author:maozl
 * date:2022/6/16
 */
@RestController
@RequestMapping("/ability/vod")
@CrossOrigin
public class VodController {


    @Autowired
    private VodService vodService;

    @Autowired
    private RedisTemplate<String,String> redisTemplate;

    /**
     * 上传视频
     * @param file 视频文件
     * @param cateId 课程所属二级分类cateId
     * @return videoId
     */
    @PostMapping("/upload")
    public R uploadVideo(@RequestParam("file") MultipartFile file, @RequestParam String cateId){

        String videoId = vodService.uploadVideo(file,cateId);
        return R.ok().message("视频上传成功").data("videoId", videoId);
    }

    /**
     * 获取视频上传进度
     * @return progressData
     */
    @GetMapping ("/percent")
    public R getUploadPercent(){
    
        String progressData = redisTemplate.opsForValue().get("progressData");
        return R.ok().data("progressData",progressData);
    }

}


业务实现层

package com.ruiya.vod.service.impl;


import com.aliyun.vod.upload.impl.UploadVideoImpl;
import com.aliyun.vod.upload.req.UploadStreamRequest;
import com.aliyun.vod.upload.resp.UploadStreamResponse;
import com.aliyuncs.DefaultAcsClient;
import com.aliyuncs.exceptions.ClientException;
import com.aliyuncs.vod.model.v20170321.DeleteVideoRequest;
import com.ruiya.commons.handler.ServiceErrorException;
import com.ruiya.commons.utils.ResultCode;
import com.ruiya.vod.listener.PutVodProgressListener;
import com.ruiya.vod.service.VodService;
import com.ruiya.vod.utils.InitClientUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.io.InputStream;

/**
 * description:阿里云点播服务业务层
 * author:maozl
 * date:2022/6/16
 */
@Service
@Slf4j
public class VodServiceImpl implements VodService {

    private static final String ACCESS_KEY_ID = "XXX";

    private static final String ACCESS_KEY_SECRET = "XXX";

    private static final String STORAGE_LOCATION = "XXX";

    /**
     * 注入自定义回调函数实现类
     */
    @Autowired
    private PutVodProgressListener putVodProgressListener;

    /**
     * 上传视频
     * @param file
     * @param cateId
     * @return
     */
    @Override
    public String uploadVideo(MultipartFile file,String cateId) {

        String videoId = null;

        try {
            String originalFilename = file.getOriginalFilename();
            String title = originalFilename.substring(0, originalFilename.lastIndexOf("."));

            //原始文件的总字节数
            long totalBytes = file.getSize();
            putVodProgressListener.setTotalBytes(totalBytes);

            //获取文件的输入流
            InputStream inputStream = file.getInputStream();

            UploadStreamRequest request = new UploadStreamRequest(ACCESS_KEY_ID, ACCESS_KEY_SECRET, title, originalFilename, inputStream);

            //存储区域
            request.setStorageLocation(STORAGE_LOCATION);

            //开启默认上传进度回调
            request.setPrintProgress(true);
            request.setProgressListener(putVodProgressListener);

            //视频分类ID
            if (!StringUtils.isEmpty(cateId)){
                request.setCateId(Long.valueOf(cateId));
            }

            UploadVideoImpl uploader = new UploadVideoImpl();
            UploadStreamResponse response = uploader.uploadStream(request);

            videoId = response.getVideoId();

            if (!response.isSuccess()) {
                String errorMessage = "视频上传错误:" + "code:" + response.getCode() + ", message:" + response.getMessage();
                log.error("上传视频出错 - {}", errorMessage);
                if(StringUtils.isEmpty(videoId)){
                    throw new ServiceErrorException(ResultCode.ERROR, errorMessage);
                }
            }
            log.debug("视频上传成功 - videoID:{}", videoId);
            return videoId;
        } catch (IOException e) {
            e.printStackTrace();
            log.error("上传视频失败 - {}",e);
            throw new ServiceErrorException(ResultCode.ERROR, "视频点播服务上传失败");
        }

    }
}

上传进度回调方法类

package com.ruiya.vod.listener;

import com.aliyun.oss.event.ProgressEvent;
import com.aliyun.oss.event.ProgressEventType;
import com.aliyun.vod.upload.impl.VoDProgressListener;
import lombok.SneakyThrows;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;

/**
 * description:上传进度回调方法类
 * author:maozl
 * date:2022/6/16
 */
@Component
public class PutVodProgressListener implements VoDProgressListener {

    @Autowired
    private RedisTemplate<String, String> redisTemplate;

    /**
     * 已成功上传至OSS的字节数
     */
    private long bytesWritten = 0;

    /**
     * 原始文件的总字节数
     */

    private long totalBytes;
    /**
     * 本次上传成功标记
     */
    private boolean succeed = false;
    /**
     * 视频ID
     */
    private String videoId;
    /**
     * 图片ID
     */
    private String imageId;

    //构造函数中加入上传文件的总大小
    public PutVodProgressListener() {
        totalBytes = -1;
    }

    public PutVodProgressListener(long totalBytes) {
        this.totalBytes = -1;
        this.totalBytes = totalBytes;
        System.out.println("初始化回调函数 - 待上传文件的总大小为:" + totalBytes);
    }

    @SneakyThrows
    @Override
    public void progressChanged(ProgressEvent progressEvent) {
        long bytes = progressEvent.getBytes();
        ProgressEventType eventType = progressEvent.getEventType();
        switch (eventType) {
            //开始上传事件
            case TRANSFER_STARTED_EVENT:
                //每次开始前,重置bytesWritten的值(不重置会导致后续上传进度超过百分之百)
                this.bytesWritten = 0;
                if (videoId != null) {
                    System.out.println("Start to upload videoId " + videoId + "......");
                }
                if (imageId != null) {
                    System.out.println("Start to upload imageId " + imageId + "......");
                }
                break;
            //计算待上传文件总大小事件通知,只有调用本地文件方式上传时支持该事件
            case REQUEST_CONTENT_LENGTH_EVENT:
                this.totalBytes = bytes;
                System.out.println(this.totalBytes + "bytes in total will be uploaded to OSS.");
                break;
            //已经上传成功文件大小事件通知
            case REQUEST_BYTE_TRANSFER_EVENT:
                this.bytesWritten += bytes;
                if (this.totalBytes != -1) {
                    int percent = (int) (this.bytesWritten * 100.0 / this.totalBytes);
                    System.out.println(bytes + " bytes have been written at this time, upload progress: " +
                            percent + "%(" + this.bytesWritten + "/" + this.totalBytes + ")");
                    //redis解决视频上传进度问题
                    redisTemplate.opsForValue().set("progressData", String.valueOf(percent));
                } else {
                    System.out.println(bytes + " bytes have been written at this time, upload sub total : " +
                            "(" + this.bytesWritten + ")");
                }
                break;
            //文件全部上传成功事件通知
            case TRANSFER_COMPLETED_EVENT:
                this.succeed = true;
                if (videoId != null) {
                    System.out.println("Succeed to upload videoId " + videoId + " , " + this.bytesWritten + " bytes have been transferred in total.");
                }
                if (imageId != null) {
                    System.out.println("Succeed to upload imageId " + imageId + " , " + this.bytesWritten + " bytes have been transferred in total.");
                }
                break;
            //文件上传失败事件通知
            case TRANSFER_FAILED_EVENT:
                if (videoId != null) {
                    System.out.println("Failed to upload videoId " + videoId + " , " + this.bytesWritten + " bytes have been transferred.");
                }
                if (imageId != null) {
                    System.out.println("Failed to upload imageId " + imageId + " , " + this.bytesWritten + " bytes have been transferred.");
                }
                break;

            default:
                break;
        }
    }

    public long getTotalBytes() {
        return totalBytes;
    }

    public void setTotalBytes(long totalBytes) {
        this.totalBytes = totalBytes;
    }

    public boolean isSucceed() {
        return succeed;
    }

    @Override
    public void onVidReady(String videoId) {
        setVideoId(videoId);
    }

    @Override
    public void onImageIdReady(String imageId) {
        setImageId(imageId);
    }

    public String getVideoId() {
        return videoId;
    }

    public void setVideoId(String videoId) {
        this.videoId = videoId;
    }

    public String getImageId() {
        return imageId;
    }

    public void setImageId(String imageId) {
        this.imageId = imageId;
    }



}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值