阿里云视频点播服务流式上传返回前端进度条
提示:前后端分离项目,流式上传到视频点播服务获取实时上传进度
阿里云视频点播服务流式上传返回前端进度条
实现思路:在阿里云的回调方法中,将上传的进度实时存入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 {@Autowiredprivate VodService vodService;@Autowiredprivate 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";/*** 注入自定义回调函数实现类*/@Autowiredprivate PutVodProgressListener putVodProgressListener;/*** 上传视频* @param file* @param cateId* @return*/@Overridepublic 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);//视频分类IDif (!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 {@Autowiredprivate 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@Overridepublic 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;}@Overridepublic void onVidReady(String videoId) {setVideoId(videoId);}@Overridepublic 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;}}
本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!
