| @@ -154,7 +154,7 @@ public class ShiroConfig { | |||
| filterChainDefinitionMap.put("/logout", "authc"); | |||
| filterChainDefinitionMap.put("/**", "corsFilter,token,authc"); | |||
| // filterChainDefinitionMap.put("/**", "anon"); | |||
| filterChainDefinitionMap.put("/**", "anon"); | |||
| shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap); | |||
| @@ -73,14 +73,6 @@ public class VideoController extends BaseController { | |||
| @Autowired | |||
| String videoType; | |||
| @GetMapping("/test") | |||
| @ApiImplicitParams({ | |||
| @ApiImplicitParam(name = "title", value = "页数", dataType = "String", paramType = "query", required = true)}) | |||
| public ResultData list(@ModelAttribute WxPropertyContract wxPropertyContract, String title) { | |||
| VideUploadResult result = videoFactory.getExcutor(videoType).uploadLocalVideo("123123213", "C:\\Users\\xiaohu\\Desktop\\111.mp4"); | |||
| return new ResultData(result); | |||
| } | |||
| /** | |||
| * 上传视频 | |||
| * | |||
| @@ -104,7 +96,7 @@ public class VideoController extends BaseController { | |||
| if(!fileFormat.endsWith("mp4")){ | |||
| return new ResultData(ErrorCode.PICTURE_ENDWIDTH_ERROR); | |||
| } | |||
| VideUploadResult result = videoFactory.getExcutor(videoType).uploadLocalVideo(title, multiReq.getInputStream(),fileFormat); | |||
| VideUploadResult result = videoFactory.getExcutor(videoType).uploadVideoStream(title, multiReq.getInputStream(),fileFormat); | |||
| return new ResultData(result); | |||
| } catch (Exception e) { | |||
| logger.error(e.getMessage()); | |||
| @@ -132,5 +124,26 @@ public class VideoController extends BaseController { | |||
| return new ResultData(ErrorCode.PICTURE_ANALYZING_ERROR); | |||
| } | |||
| } | |||
| /** | |||
| * 上传视频 | |||
| * | |||
| * @param multiReq | |||
| * @return | |||
| * @throws Exception | |||
| */ | |||
| @GetMapping(value = "/videoContentLength") | |||
| @ApiOperation("上传视频进度") | |||
| @ApiImplicitParams({ | |||
| @ApiImplicitParam(name = "videoId", value = "视频编号", dataType = "String", paramType = "query", required = true)}) | |||
| public ResultData videoContentLength(String videoId) { | |||
| try { | |||
| String result = videoFactory.getExcutor(videoType).getVedioContentLength(videoId); | |||
| return new ResultData(result); | |||
| } catch (Exception e) { | |||
| logger.error(e.getMessage()); | |||
| return new ResultData(ErrorCode.PICTURE_ANALYZING_ERROR); | |||
| } | |||
| } | |||
| } | |||
| @@ -172,6 +172,11 @@ video: | |||
| accessKeyId: LTAI4G7ixY4AhvM35F8o3W3V | |||
| accessKeySecret: VfWqGb83qIQrS9us45utskl8itd7ry | |||
| regionId: cn-beijing | |||
| endPoint: https://oss-cn-beijing.aliyuncs.com | |||
| corePoolSize: 6 | |||
| maxPoolSize: 20 | |||
| queueCapacity: 1000 | |||
| namePrefix: aliyun-video-upload | |||
| jasypt: | |||
| @@ -14,8 +14,8 @@ spring: | |||
| default-property-inclusion: non_null | |||
| servlet: | |||
| multipart: | |||
| max-file-size: 20MB | |||
| max-request-size: 200MB | |||
| max-file-size: 300MB | |||
| max-request-size: 1024MB | |||
| cache: | |||
| type: REDIS | |||
| cache-names: redis_cache #缓存的名字(可以不指定) | |||
| @@ -8,50 +8,37 @@ | |||
| <version>1.0</version> | |||
| </parent> | |||
| <modelVersion>4.0.0</modelVersion> | |||
| <artifactId>mallinkVideo</artifactId> | |||
| <repositories> | |||
| <repository> | |||
| <id>sonatype-nexus-staging</id> | |||
| <name>Sonatype Nexus Staging</name> | |||
| <url>https://oss.sonatype.org/service/local/staging/deploy/maven2/</url> | |||
| <releases> | |||
| <enabled>true</enabled> | |||
| </releases> | |||
| <snapshots> | |||
| <enabled>true</enabled> | |||
| </snapshots> | |||
| </repository> | |||
| </repositories> | |||
| <dependencies> | |||
| <dependency> | |||
| <groupId>com.aliyun</groupId> | |||
| <artifactId>aliyun-java-sdk-core</artifactId> | |||
| <version>4.5.1</version> | |||
| </dependency> | |||
| <dependency> | |||
| <groupId>com.aliyun.oss</groupId> | |||
| <artifactId>aliyun-sdk-oss</artifactId> | |||
| <version>3.10.2</version> | |||
| </dependency> | |||
| <dependency> | |||
| <groupId>com.aliyun</groupId> | |||
| <artifactId>aliyun-java-sdk-vod</artifactId> | |||
| <version>2.15.11</version> | |||
| </dependency> | |||
| <!-- 引入外包 --> | |||
| <!-- mvn install:install-file -Dfile=/lib/aliyun-java-vod-upload-1.4.14.jar -DgroupId=com.aliyun -DartifactId=aliyun-java-vod-upload -Dversion=1.4.14 -Dpackaging=jar --> | |||
| <dependency> | |||
| <groupId>com.aliyun</groupId> | |||
| <artifactId>aliyun-java-vod-upload</artifactId> | |||
| <version>1.4.14</version> | |||
| <!-- <scope>system</scope> | |||
| <systemPath>${basedir}/src/main/resources/lib/aliyun-java-vod-upload-1.4.14.jar</systemPath> --> | |||
| </dependency> | |||
| <dependency> | |||
| <groupId>com.alibaba</groupId> | |||
| <artifactId>fastjson</artifactId> | |||
| <version>1.2.62</version> | |||
| </dependency> | |||
| <dependency> | |||
| <groupId>org.json</groupId> | |||
| <artifactId>json</artifactId> | |||
| <version>20170516</version> | |||
| </dependency> | |||
| <dependency> | |||
| <groupId>com.google.code.gson</groupId> | |||
| <artifactId>gson</artifactId> | |||
| <version>2.8.2</version> | |||
| </dependency> | |||
| <dependency> | |||
| <groupId>com.aliyun</groupId> | |||
| <artifactId>aliyun-java-sdk-core</artifactId> | |||
| <version>4.5.1</version> | |||
| </dependency> | |||
| <dependency> | |||
| <groupId>com.aliyun</groupId> | |||
| <artifactId>aliyun-java-sdk-vod</artifactId> | |||
| <version>2.15.11</version> | |||
| </dependency> | |||
| <dependency> | |||
| <groupId>com.alibaba</groupId> | |||
| <artifactId>fastjson</artifactId> | |||
| <version>1.2.62</version> | |||
| </dependency> | |||
| </dependencies> | |||
| </project> | |||
| @@ -11,14 +11,11 @@ public interface VideoExcutor { | |||
| * 上传视频 | |||
| * title:视频标题 | |||
| */ | |||
| public VideUploadResult uploadLocalVideo(String title,String localFile); | |||
| public VideUploadResult uploadLocalVideo(String title,InputStream inputStream,String fileFormat); | |||
| //ext,后缀名 | |||
| public VideUploadResult uploadNetVideo(String title,String url,String ext); | |||
| public VideUploadResult uploadVideoStream(String title,InputStream inputStream,String ex); | |||
| public String getVedioUploadProgress(String videoId); | |||
| public String getVedioContentLength(String videoId); | |||
| VideUploadResult getVideoDetail(String videoId); | |||
| } | |||
| @@ -1,26 +1,28 @@ | |||
| package com.iformall.video.aliyun; | |||
| import java.io.IOException; | |||
| import java.io.File; | |||
| import java.io.InputStream; | |||
| import java.util.List; | |||
| import java.util.UUID; | |||
| import com.aliyuncs.vod.model.v20170321.CreateUploadVideoResponse; | |||
| import com.aliyuncs.vod.model.v20170321.GetPlayInfoResponse; | |||
| import com.baomidou.mybatisplus.core.toolkit.IdWorker; | |||
| import org.apache.commons.io.FileUtils; | |||
| import org.springframework.beans.factory.annotation.Autowired; | |||
| import org.springframework.beans.factory.annotation.Qualifier; | |||
| import org.springframework.data.redis.core.RedisTemplate; | |||
| import org.springframework.stereotype.Component; | |||
| import com.aliyun.vod.upload.resp.UploadStreamResponse; | |||
| import com.aliyun.vod.upload.resp.UploadURLStreamResponse; | |||
| import com.aliyun.vod.upload.resp.UploadVideoResponse; | |||
| import com.aliyuncs.DefaultAcsClient; | |||
| import com.aliyuncs.exceptions.ClientException; | |||
| import com.aliyuncs.profile.DefaultProfile; | |||
| import com.iformall.video.VideoExcutor; | |||
| import com.iformall.video.aliyun.config.AliyunVideoConfig; | |||
| import com.iformall.video.aliyun.sdk.server.AliyunVedioServer; | |||
| import com.iformall.video.aliyun.sdk.upload.AliyunVedioUpload; | |||
| import com.iformall.video.aliyun.sdk.server.UploadCacheHelper; | |||
| import com.iformall.video.aliyun.thread.AliyunVideoUploadThread; | |||
| import com.iformall.video.entity.VideUploadResult; | |||
| import lombok.extern.slf4j.Slf4j; | |||
| @Component | |||
| @@ -30,6 +32,9 @@ public class AliyunVideoExcutor implements VideoExcutor { | |||
| @Autowired | |||
| AliyunVideoConfig config; | |||
| @Autowired | |||
| AliyunVideoUploadThread thread; | |||
| @Autowired | |||
| @Qualifier("objectCommonRedisTemplate") | |||
| RedisTemplate<String, Object> redisTemplate; | |||
| @@ -43,20 +48,35 @@ public class AliyunVideoExcutor implements VideoExcutor { | |||
| return null; | |||
| } | |||
| public DefaultAcsClient initVodClient() throws ClientException { | |||
| String regionId = config.getRegionId(); // 点播服务接入区域 | |||
| DefaultProfile profile = DefaultProfile.getProfile(regionId, config.getAccessKeyId(), config.getAccessKeySecret()); | |||
| DefaultAcsClient client = new DefaultAcsClient(profile); | |||
| return client; | |||
| } | |||
| /** | |||
| * https://help.aliyun.com/document_detail/61063.html?spm=a2c4g.11186623.6.1036.2f81d418ydqsX8 | |||
| * https://help.aliyun.com/document_detail/55407.htm?spm=a2c4g.11186623.2.12.77aad4180Hg9y0#doc-api-vod-CreateUploadVideo | |||
| */ | |||
| @Override | |||
| public VideUploadResult uploadLocalVideo(String title,String localFile) { | |||
| public VideUploadResult uploadVideoStream(String title,InputStream inputStream,String ex) { | |||
| VideUploadResult result = new VideUploadResult(); | |||
| try { | |||
| UploadVideoResponse response =AliyunVedioUpload.uploadVideo(config.getAccessKeyId(), config.getAccessKeySecret(),config.getRegionId(), title, localFile,redisTemplate); | |||
| if (response.isSuccess()) { | |||
| result.setVideoId(response.getVideoId()); | |||
| result.setVideoUrl(getUrlByVeidoId(response.getVideoId())); | |||
| result.setSuccess(true); | |||
| }else { | |||
| //如果设置回调URL无效,不影响视频上传,可以返回VideoId同时会返回错误码。其他情况上传失败时,VideoId为空,此时需要根据返回错误码分析具体错误原因 | |||
| result.setSuccess(false); | |||
| result.setMsg("ErrorCode["+response.getCode()+"]"+response.getMessage()); | |||
| //该接口不会真正上传视频文件,您需要获得上传地址和凭证后,对其进行Base64解码,再调用OSS SDK将视频文件上传至指定的bucket中。详细操作,请参见基于OSS原生SDK上传视频到点播 | |||
| File folder = new File ("/video/upload/temp/aliyun") ; | |||
| if (!folder.exists()) { | |||
| folder.mkdirs(); | |||
| } | |||
| String _tempfilepath = "/video/upload/temp/aliyun/"+IdWorker.get32UUID()+"."+ex; | |||
| File targetFile = new File(_tempfilepath); | |||
| FileUtils.copyInputStreamToFile(inputStream, targetFile); | |||
| CreateUploadVideoResponse response =AliyunVedioServer.createUploadVideo(config, title, _tempfilepath); | |||
| result.setVideoId(response.getVideoId()); | |||
| //result.setVideoUrl(getUrlByVeidoId(response.getVideoId())); | |||
| result.setSuccess(true); | |||
| //TODO 线程池的方式 | |||
| thread.executeAysncTask(response, _tempfilepath,redisTemplate); | |||
| } catch (Exception e) { | |||
| log.error("aliyun uploadLocalVideo error",e); | |||
| result.setSuccess(false); | |||
| @@ -82,55 +102,9 @@ public class AliyunVideoExcutor implements VideoExcutor { | |||
| } | |||
| } | |||
| @Override | |||
| public VideUploadResult uploadLocalVideo(String title,InputStream inputStream,String fileFormat) { | |||
| VideUploadResult result = new VideUploadResult(); | |||
| UploadStreamResponse response; | |||
| try { | |||
| response = AliyunVedioUpload.uploadStream(config.getAccessKeyId(), config.getAccessKeySecret(),config.getRegionId(), title, UUID.randomUUID().toString().replace("-","")+fileFormat, inputStream,redisTemplate); | |||
| if (response.isSuccess()) { | |||
| result.setVideoId(response.getVideoId()); | |||
| // setVideUploadResult(result,response.getVideoId()); | |||
| result.setVideoUrl(getUrlByVeidoId(response.getVideoId())); | |||
| result.setSuccess(true); | |||
| } else { //如果设置回调URL无效,不影响视频上传,可以返回VideoId同时会返回错误码。其他情况上传失败时,VideoId为空,此时需要根据返回错误码分析具体错误原因 | |||
| result.setSuccess(false); | |||
| result.setMsg("ErrorCode["+response.getCode()+"]"+response.getMessage()); | |||
| } | |||
| } catch (Exception e) { | |||
| log.error("aliyun uploadLocalVideo error",e); | |||
| result.setSuccess(false); | |||
| result.setMsg(e.getLocalizedMessage()); | |||
| }finally { | |||
| if (null != inputStream) { | |||
| try { | |||
| inputStream.close(); | |||
| } catch (IOException e) { | |||
| } | |||
| } | |||
| } | |||
| return result; | |||
| } | |||
| @Override | |||
| public VideUploadResult uploadNetVideo(String title,String url,String ext) { | |||
| VideUploadResult result = new VideUploadResult(); | |||
| UploadURLStreamResponse response = AliyunVedioUpload.uploadURLStream(config.getAccessKeyId(), config.getAccessKeySecret(),config.getRegionId(), title, url, ext,redisTemplate); | |||
| if (response.isSuccess()) { | |||
| result.setVideoId(response.getVideoId()); | |||
| result.setVideoUrl(getUrlByVeidoId(response.getVideoId())); | |||
| result.setSuccess(true); | |||
| } else { | |||
| /* 如果设置回调URL无效,不影响视频上传,可以返回VideoId同时会返回错误码。其他情况上传失败时,VideoId为空,此时需要根据返回错误码分析具体错误原因 */ | |||
| result.setSuccess(false); | |||
| result.setMsg("ErrorCode["+response.getCode()+"]"+response.getMessage()); | |||
| } | |||
| return result; | |||
| } | |||
| @Override | |||
| public String getVedioUploadProgress(String videoId) { | |||
| return AliyunVedioUpload.getUploadProgress(redisTemplate, videoId); | |||
| return UploadCacheHelper.getUploadProgress(redisTemplate, videoId); | |||
| } | |||
| @Override | |||
| @@ -161,4 +135,9 @@ public class AliyunVideoExcutor implements VideoExcutor { | |||
| } | |||
| return result; | |||
| } | |||
| @Override | |||
| public String getVedioContentLength(String videoId) { | |||
| return UploadCacheHelper.getContentLength(redisTemplate, videoId); | |||
| } | |||
| } | |||
| @@ -12,4 +12,5 @@ public class AliyunVideoConfig { | |||
| private String accessKeyId; | |||
| private String accessKeySecret; | |||
| private String regionId;//cn-shanghai 点播服务接入区域 | |||
| private String endPoint;//以华东1(杭州)为例,Endpoint填写为https://oss-cn-hangzhou.aliyuncs.com | |||
| } | |||
| @@ -1,9 +1,26 @@ | |||
| package com.iformall.video.aliyun.sdk.server; | |||
| import java.io.File; | |||
| import java.io.IOException; | |||
| import java.io.InputStream; | |||
| import java.io.UnsupportedEncodingException; | |||
| import java.net.MalformedURLException; | |||
| import java.net.URL; | |||
| import java.util.Base64; | |||
| import java.util.List; | |||
| import org.springframework.data.redis.core.RedisTemplate; | |||
| import com.alibaba.fastjson.JSON; | |||
| import com.alibaba.fastjson.JSONObject; | |||
| import com.aliyun.oss.OSS; | |||
| import com.aliyun.oss.OSSClient; | |||
| import com.aliyun.oss.OSSClientBuilder; | |||
| import com.aliyun.oss.model.PutObjectRequest; | |||
| import com.aliyuncs.DefaultAcsClient; | |||
| import com.aliyuncs.profile.DefaultProfile; | |||
| import com.aliyuncs.vod.model.v20170321.CreateUploadVideoRequest; | |||
| import com.aliyuncs.vod.model.v20170321.CreateUploadVideoResponse; | |||
| import com.aliyuncs.vod.model.v20170321.GetPlayInfoRequest; | |||
| import com.aliyuncs.vod.model.v20170321.GetPlayInfoResponse; | |||
| import com.iformall.video.aliyun.config.AliyunVideoConfig; | |||
| @@ -22,6 +39,71 @@ public class AliyunVedioServer { | |||
| return client; | |||
| } | |||
| /** | |||
| * 获取视频上传地址和凭证 | |||
| * @param client 发送请求客户端 | |||
| * @return CreateUploadVideoResponse 获取视频上传地址和凭证响应数据 | |||
| * @throws Exception | |||
| */ | |||
| public static CreateUploadVideoResponse createUploadVideo(AliyunVideoConfig config,String title,String fileName) throws Exception { | |||
| DefaultAcsClient client = initVodClient(config); | |||
| CreateUploadVideoRequest request = new CreateUploadVideoRequest(); | |||
| request.setTitle(title); | |||
| request.setFileName(fileName); | |||
| //UserData,用户自定义设置参数,用户需要单独回调URL及数据透传时设置(非必须) | |||
| //JSONObject userData = new JSONObject(); | |||
| //UserData回调部分设置 | |||
| //JSONObject messageCallback = new JSONObject(); | |||
| //messageCallback.put("CallbackURL", "http://192.168.0.0/16"); | |||
| //messageCallback.put("CallbackType", "http"); | |||
| //userData.put("MessageCallback", messageCallback.toJSONString()); | |||
| //UserData透传数据部分设置 | |||
| //JSONObject extend = new JSONObject(); | |||
| //extend.put("MyId", "user-defined-id"); | |||
| //userData.put("Extend", extend.toJSONString()); | |||
| //request.setUserData(userData.toJSONString()); | |||
| return client.getAcsResponse(request); | |||
| } | |||
| private static OssUploadClient initOssClient(CreateUploadVideoResponse response) throws UnsupportedEncodingException { | |||
| final Base64.Decoder decoder = Base64.getDecoder(); | |||
| String uploadAddressStr = new String(decoder.decode(response.getUploadAddress().getBytes("UTF-8"))); | |||
| String uploadAuthStr = new String(decoder.decode(response.getUploadAuth().getBytes("UTF-8"))); | |||
| JSONObject uploadAuth = JSON.parseObject(uploadAuthStr); | |||
| JSONObject uploadAddress = JSON.parseObject(uploadAddressStr); | |||
| String bucket = uploadAddress.getString("Bucket"); | |||
| String endpoint = uploadAddress.getString("Endpoint"); | |||
| String fileName = uploadAddress.getString("FileName"); | |||
| String accessKeyId = uploadAuth.getString("AccessKeyId"); | |||
| String accessKeySecret = uploadAuth.getString("AccessKeySecret"); | |||
| String securityToken = uploadAuth.getString("SecurityToken"); | |||
| OSS client = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret); | |||
| return new OssUploadClient(bucket, endpoint, fileName, client); | |||
| } | |||
| public static void uploadVideo(CreateUploadVideoResponse response,String localFile,RedisTemplate<String, Object> redisTemplate) throws UnsupportedEncodingException { | |||
| OssUploadClient ossClient = initOssClient(response); | |||
| // 创建PutObjectRequest对象。 | |||
| // 填写Bucket名称、Object完整路径和本地文件的完整路径。Object完整路径中不能包含Bucket名称。 | |||
| // 如果未指定本地路径,则默认从示例程序所属项目对应本地路径中上传文件。 | |||
| //PutObjectRequest putObjectRequest = new PutObjectRequest(ossClient.getBucket(), ossClient.getFileName(), new File(localFile)); | |||
| // 如果需要上传时设置存储类型和访问权限,请参考以下示例代码。 | |||
| // ObjectMetadata metadata = new ObjectMetadata(); | |||
| // metadata.setHeader(OSSHeaders.OSS_STORAGE_CLASS, StorageClass.Standard.toString()); | |||
| // metadata.setObjectAcl(CannedAccessControlList.Private); | |||
| // putObjectRequest.setMetadata(metadata); | |||
| // 上传文件。 | |||
| ossClient.getOssClient().putObject(new PutObjectRequest(ossClient.getBucket(), ossClient.getFileName(), new File(localFile)). | |||
| <PutObjectRequest>withProgressListener(new PutObjectProgressListener(redisTemplate,response.getVideoId(),localFile))); | |||
| // 关闭OSSClient。 | |||
| ossClient.getOssClient().shutdown(); | |||
| } | |||
| //获取视频播放地址 | |||
| //https://help.aliyun.com/document_detail/61064.html?spm=a2c4g.11186623.6.1043.7c2d3838K6wQPZ | |||
| public static String getVedioUrl(AliyunVideoConfig config,String videoId) throws ClientException { | |||
| @@ -0,0 +1,16 @@ | |||
| package com.iformall.video.aliyun.sdk.server; | |||
| import com.aliyun.oss.OSS; | |||
| import lombok.AllArgsConstructor; | |||
| import lombok.Data; | |||
| @Data | |||
| @AllArgsConstructor | |||
| public class OssUploadClient { | |||
| private String bucket; | |||
| private String endpoint; | |||
| private String fileName; | |||
| private OSS ossClient; | |||
| } | |||
| @@ -0,0 +1,90 @@ | |||
| package com.iformall.video.aliyun.sdk.server; | |||
| import java.io.File; | |||
| import org.apache.commons.lang3.StringUtils; | |||
| import org.springframework.data.redis.core.RedisTemplate; | |||
| import com.aliyun.oss.event.ProgressEvent; | |||
| import com.aliyun.oss.event.ProgressEventType; | |||
| import com.aliyun.oss.event.ProgressListener; | |||
| public class PutObjectProgressListener implements ProgressListener{ | |||
| private String videoId = ""; | |||
| private String localFile = ""; | |||
| private long bytesWritten = 0; | |||
| private long totalBytes = -1; | |||
| private boolean succeed = false; | |||
| private RedisTemplate<String, Object> redisTemplate; | |||
| public PutObjectProgressListener(RedisTemplate<String, Object> redisTemplate,String videoId,String localFile) { | |||
| this.redisTemplate = redisTemplate; | |||
| this.videoId = videoId; | |||
| this.localFile = localFile; | |||
| } | |||
| @Override | |||
| public void progressChanged(ProgressEvent progressEvent) { | |||
| long bytes = progressEvent.getBytes(); | |||
| ProgressEventType eventType = progressEvent.getEventType(); | |||
| switch (eventType) { | |||
| case TRANSFER_STARTED_EVENT: | |||
| if (null != redisTemplate && (!StringUtils.isBlank(videoId))) { | |||
| UploadCacheHelper.cacheStart(redisTemplate, videoId); | |||
| } | |||
| //System.out.println("Start to upload......"); | |||
| break; | |||
| case REQUEST_CONTENT_LENGTH_EVENT: | |||
| this.totalBytes = bytes; | |||
| if (null != redisTemplate && (!StringUtils.isBlank(videoId))) { | |||
| UploadCacheHelper.setContentLength(redisTemplate, videoId, String.valueOf(this.totalBytes)); | |||
| } | |||
| //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 + ")"); | |||
| } else { | |||
| //System.out.println(bytes + " bytes have been written at this time, upload ratio: unknown" + "(" + this.bytesWritten + "/...)"); | |||
| } | |||
| if (null != redisTemplate && (!StringUtils.isBlank(videoId))) { | |||
| UploadCacheHelper.cacheProgress(redisTemplate, videoId, String.valueOf(this.bytesWritten)); | |||
| } | |||
| break; | |||
| case TRANSFER_COMPLETED_EVENT: | |||
| this.succeed = true; | |||
| if (null != redisTemplate && (!StringUtils.isBlank(videoId))) { | |||
| UploadCacheHelper.cacheComplete(redisTemplate, videoId); | |||
| } | |||
| if (!StringUtils.isBlank(localFile)) { | |||
| File f = new File(localFile); | |||
| if (f.exists()) { | |||
| f.delete(); | |||
| } | |||
| } | |||
| //System.out.println("Succeed to upload, " + this.bytesWritten + " bytes have been transferred in total"); | |||
| break; | |||
| case TRANSFER_FAILED_EVENT: | |||
| //System.out.println("Failed to upload, " + this.bytesWritten + " bytes have been transferred"); | |||
| if (null != redisTemplate && (!StringUtils.isBlank(videoId))) { | |||
| UploadCacheHelper.cacheError(redisTemplate, videoId); | |||
| } | |||
| if (!StringUtils.isBlank(localFile)) { | |||
| File f = new File(localFile); | |||
| if (f.exists()) { | |||
| f.delete(); | |||
| } | |||
| } | |||
| break; | |||
| default: | |||
| break; | |||
| } | |||
| } | |||
| public boolean isSucceed() { | |||
| return succeed; | |||
| } | |||
| } | |||
| @@ -0,0 +1,59 @@ | |||
| package com.iformall.video.aliyun.sdk.server; | |||
| import java.util.concurrent.TimeUnit; | |||
| import org.springframework.data.redis.core.RedisTemplate; | |||
| import org.springframework.data.redis.core.ValueOperations; | |||
| public class UploadCacheHelper { | |||
| private static String PRE = "video:upload:aliyun:progress:"; | |||
| public static void cacheStart(RedisTemplate<String, Object> template,String videoId) { | |||
| ValueOperations<String, Object> operations = template.opsForValue(); | |||
| operations.set(PRE+videoId, "begin", 24*3600,TimeUnit.SECONDS); | |||
| } | |||
| public static void cacheComplete(RedisTemplate<String, Object> template,String videoId) { | |||
| ValueOperations<String, Object> operations = template.opsForValue(); | |||
| operations.set(PRE+videoId, "complete", 24*3600,TimeUnit.SECONDS); | |||
| } | |||
| public static void cacheProgress(RedisTemplate<String, Object> template,String videoId,String bytes) { | |||
| ValueOperations<String, Object> operations = template.opsForValue(); | |||
| operations.set(PRE+videoId, bytes, 24*3600,TimeUnit.SECONDS); | |||
| } | |||
| public static void cacheError(RedisTemplate<String, Object> template,String videoId) { | |||
| ValueOperations<String, Object> operations = template.opsForValue(); | |||
| operations.set(PRE+videoId, "error", 24*3600,TimeUnit.SECONDS); | |||
| } | |||
| public static String getUploadProgress(RedisTemplate<String, Object> template,String videoId) { | |||
| if (template.hasKey(PRE+videoId)) { | |||
| ValueOperations<String, Object> operations = template.opsForValue(); | |||
| Object o = operations.get(PRE+videoId); | |||
| if (o instanceof String) { | |||
| return (String)o; | |||
| } | |||
| } | |||
| return null; | |||
| } | |||
| public static void setContentLength(RedisTemplate<String, Object> template,String videoId,String length) { | |||
| ValueOperations<String, Object> operations = template.opsForValue(); | |||
| operations.set("video:upload:aliyun:contengLength:"+videoId, length, 24*3600,TimeUnit.SECONDS); | |||
| } | |||
| public static String getContentLength(RedisTemplate<String, Object> template,String videoId) { | |||
| if (template.hasKey("video:upload:aliyun:contengLength:"+videoId)) { | |||
| ValueOperations<String, Object> operations = template.opsForValue(); | |||
| Object o = operations.get("video:upload:aliyun:contengLength:"+videoId); | |||
| if (o instanceof String) { | |||
| return (String)o; | |||
| } | |||
| } | |||
| return null; | |||
| } | |||
| } | |||
| @@ -1,695 +0,0 @@ | |||
| package com.iformall.video.aliyun.sdk.upload; | |||
| import java.io.FileInputStream; | |||
| import java.io.FileNotFoundException; | |||
| import java.io.IOException; | |||
| import java.io.InputStream; | |||
| import java.net.URL; | |||
| import org.springframework.data.redis.core.RedisTemplate; | |||
| import com.aliyun.vod.upload.impl.UploadAttachedMediaImpl; | |||
| import com.aliyun.vod.upload.impl.UploadImageImpl; | |||
| import com.aliyun.vod.upload.impl.UploadM3u8FileImpl; | |||
| import com.aliyun.vod.upload.impl.UploadVideoImpl; | |||
| import com.aliyun.vod.upload.req.UploadAttachedMediaRequest; | |||
| import com.aliyun.vod.upload.req.UploadFileStreamRequest; | |||
| import com.aliyun.vod.upload.req.UploadImageRequest; | |||
| import com.aliyun.vod.upload.req.UploadLocalM3u8Request; | |||
| import com.aliyun.vod.upload.req.UploadStreamRequest; | |||
| import com.aliyun.vod.upload.req.UploadURLStreamRequest; | |||
| import com.aliyun.vod.upload.req.UploadVideoRequest; | |||
| import com.aliyun.vod.upload.req.UploadWebM3u8Request; | |||
| import com.aliyun.vod.upload.resp.UploadAttachedMediaResponse; | |||
| import com.aliyun.vod.upload.resp.UploadFileStreamResponse; | |||
| import com.aliyun.vod.upload.resp.UploadImageResponse; | |||
| import com.aliyun.vod.upload.resp.UploadLocalM3u8Response; | |||
| import com.aliyun.vod.upload.resp.UploadStreamResponse; | |||
| import com.aliyun.vod.upload.resp.UploadURLStreamResponse; | |||
| import com.aliyun.vod.upload.resp.UploadVideoResponse; | |||
| import com.aliyun.vod.upload.resp.UploadWebM3u8Response; | |||
| import lombok.extern.slf4j.Slf4j; | |||
| /** | |||
| * 以下Java示例代码演示了如何在服务端上传媒资文件至视频点播,媒资类型支持音频、视频和图片。 | |||
| * <p> | |||
| * 一、音视频上传目前支持4种方式上传: | |||
| * | |||
| * 1.上传本地文件,使用分片上传,并支持断点续传,参见testUploadVideo函数。 | |||
| * 1.1 当断点续传关闭时,最大支持上传任务执行时间为3000秒,具体可上传文件大小与您的网络带宽及磁盘读写能力有关。 | |||
| * 1.2 当断点续传开启时,最大支持48.8TB的单个文件,注意,断点续传开启后,上传任务执行过程中,同时会将当前上传位置写入本地磁盘文件,影响您上传文件的速度,请您根据文件大小选择是否开启 | |||
| * | |||
| * 2.上传网络流,可指定文件URL进行上传,支持断点续传,最大支持48.8TB的单个文件。 | |||
| * 该上传方式需要先将网络文件下载到本地磁盘,再进行上传,所以要保证本地磁盘有充足的空间。参见testUploadURLStream函数。 | |||
| * | |||
| * 3.上传文件流,可指定本地文件进行上传,不支持断点续传,最大支持5GB的单个文件。参见testUploadFileStream函数。 | |||
| * | |||
| * 4.流式上传,可指定输入流进行上传,支持文件流和网络流等,不支持断点续传,最大支持5GB的单个文件。参见testUploadStream函数。 | |||
| * <p> | |||
| * | |||
| * 二、图片上传目前支持2种方式上传: | |||
| * 1.上传本地文件,不支持断点续传,最大支持5GB的单个文件,参见testUploadImageLocalFile函数 | |||
| * 2.上传文件流和网络流,InputStream参数必选,不支持断点续传,最大支持5GB的单个文件。参见testUploadImageStream函数。 | |||
| * 注:图片上传完成后,会返回图片ID和图片地址,也可通过GetImageInfo查询图片信息,参见接口文档 https://help.aliyun.com/document_detail/89742.html | |||
| * <p> | |||
| * | |||
| * 三、m3u8文件上传目前支持2种方式: | |||
| * 1.上传本地m3u8音视频文件(包括所有分片文件)到点播,需指定本地m3u8索引文件地址和所有分片地址。 | |||
| * 2.上传网络m3u8音视频文件(包括所有分片文件)到点播,需指定m3u8索引文件和分片文件的URL地址。 | |||
| * | |||
| * 注: | |||
| * 1) 上传网络m3u8音视频文件时需要保证地址可访问,如果有权限限制,请设置带签名信息的地址,且保证足够长的有效期,防止地址无法访问导致上传失败 | |||
| * 2) m3u8文件上传暂不支持进度回调 | |||
| * <p> | |||
| * | |||
| * 四、上传进度回调通知: | |||
| * 1.默认上传进度回调函数:视频点播上传SDK内部默认开启上传进度回调函数,输出不同事件通知的日志,您可以设置关闭该上传进度通知及日志输出; | |||
| * 2.自定义上传进度回调函数:您可根据自已的业务场景重新定义不同事件处理的方式,只需要修改上传回调示例函数即可。 | |||
| * <p> | |||
| * | |||
| * 五、辅助媒资上传目前支持2种方式: | |||
| * 1.上传本地文件,不支持断点续传,最大支持5GB的单个文件,参见testUploadAttachedMediaLocalFile函数 | |||
| * 2.上传文件流和网络流,InputStream参数必选,不支持断点续传,最大支持5GB的单个文件。参见testUploadAttachedMediaStream函数。 | |||
| * <p> | |||
| * | |||
| * 六、支持STS方式上传: | |||
| * 1.您需要实现VoDRefreshSTSTokenListener接口的onRefreshSTSToken方法,用于生成STS信息, | |||
| * 当文件上传时间超过STS过期时间时,SDK内部会定期调用此方法刷新您的STS信息进行后续文件的上传。 | |||
| * <p> | |||
| * | |||
| * 七、可指定上传脚本部署的ECS区域(设置Request的EcsRegionId参数,取值参考存储区域标识:https://help.aliyun.com/document_detail/98194.html), | |||
| * 如果与点播存储(OSS)区域相同,则自动使用内网上传文件至存储,上传更快且更省公网流量 | |||
| * 由于点播API只提供外网域名访问,因此部署上传脚本的ECS服务器必须具有访问外网的权限。 | |||
| * | |||
| * 注意: | |||
| * 请替换示例中的必选参数,示例中的可选参数如果您不需要设置,请将其删除,以免设置无效参数值与您的预期不符。 | |||
| */ | |||
| @Slf4j | |||
| public class AliyunVedioUpload { | |||
| public static void main(String[] args) { | |||
| //账号AK信息请填写(必选) | |||
| String accessKeyId = "<Your accessKeyId>"; | |||
| //账号AK信息请填写(必选) | |||
| String accessKeySecret = "<Your accessKeySecret>"; | |||
| // 一、视频文件上传 | |||
| // 视频标题(必选) | |||
| String title = "测试标题"; | |||
| // 1.本地文件上传和文件流上传时,文件名称为上传文件绝对路径,如:/User/sample/文件名称.mp4 (必选) | |||
| // 2.网络流上传时,文件名称为源文件名,如文件名称.mp4(必选)。 | |||
| // 3.流式上传时,文件名称为源文件名,如文件名称.mp4(必选)。 | |||
| // 任何上传方式文件名必须包含扩展名 | |||
| String fileName = "/Users/test/video/test.mp4"; | |||
| // 本地文件上传 | |||
| uploadVideo(accessKeyId, accessKeySecret,"cn-beijing", title, fileName,null); | |||
| // 待上传视频的网络流地址 | |||
| String url = "http://test.aliyun.com/video/test.mp4"; | |||
| // 2.网络流上传 | |||
| // 文件扩展名,当url中不包含扩展名时,需要设置该参数 | |||
| String fileExtension = "mp4"; | |||
| uploadURLStream(accessKeyId, accessKeySecret, "cn-beijing",title, url, fileExtension,null); | |||
| // 3.文件流上传 | |||
| // testUploadFileStream(accessKeyId, accessKeySecret, title, fileName); | |||
| // 4.流式上传,如文件流和网络流 | |||
| InputStream inputStream = null; | |||
| // 4.1 文件流 | |||
| try { | |||
| inputStream = new FileInputStream(fileName); | |||
| } catch (FileNotFoundException e) { | |||
| e.printStackTrace(); | |||
| } | |||
| // 4.2 网络流 | |||
| try { | |||
| inputStream = new URL(url).openStream(); | |||
| } catch (IOException e) { | |||
| e.printStackTrace(); | |||
| } | |||
| uploadStream(accessKeyId, accessKeySecret, "cn-beijing",title, fileName, inputStream,null); | |||
| // 二、图片上传 | |||
| // 1.图片上传-本地文件上传 | |||
| // testUploadImageLocalFile(accessKeyId, accessKeySecret); | |||
| // 2.图片上传-流式上传(文件流和网络流) | |||
| // testUploadImageStream(accessKeyId, accessKeySecret); | |||
| // 三、m3u8文件上传 | |||
| // 1.上传本地m3u8音视频文件 | |||
| uploadLocalM3u8(accessKeyId, accessKeySecret,"cn-beijing"); | |||
| // 2.上传网络m3u8音视频文件 | |||
| uploadWebM3u8(accessKeyId, accessKeySecret,"cn-beijing"); | |||
| // 四、辅助媒资上传 | |||
| // 辅助媒资-本地文件上传 | |||
| // testUploadAttachedMediaLocalFile(accessKeyId, accessKeySecret); | |||
| // 辅助媒资-流式上传(文件流和网络流) | |||
| // testUploadAttachedMediaStream(accessKeyId, accessKeySecret); | |||
| } | |||
| /** | |||
| * 本地文件上传接口 | |||
| * | |||
| * @param accessKeyId | |||
| * @param accessKeySecret | |||
| * @param title | |||
| * @param fileName | |||
| */ | |||
| public static UploadVideoResponse uploadVideo(String accessKeyId, String accessKeySecret,String regionId, String title, String fileName, | |||
| RedisTemplate<String, Object> redisTemplate) { | |||
| UploadVideoRequest request = new UploadVideoRequest(accessKeyId, accessKeySecret, title, fileName); | |||
| /* 可指定分片上传时每个分片的大小,默认为2M字节 */ | |||
| request.setPartSize(2 * 1024 * 1024L); | |||
| /* 可指定分片上传时的并发线程数,默认为1,(注:该配置会占用服务器CPU资源,需根据服务器情况指定)*/ | |||
| request.setTaskNum(1); | |||
| /* 是否开启断点续传, 默认断点续传功能关闭。当网络不稳定或者程序崩溃时,再次发起相同上传请求,可以继续未完成的上传任务,适用于超时3000秒仍不能上传完成的大文件。 | |||
| 注意: 断点续传开启后,会在上传过程中将上传位置写入本地磁盘文件,影响文件上传速度,请您根据实际情况选择是否开启*/ | |||
| //request.setEnableCheckpoint(false); | |||
| /* OSS慢请求日志打印超时时间,是指每个分片上传时间超过该阈值时会打印debug日志,如果想屏蔽此日志,请调整该阈值。单位: 毫秒,默认为300000毫秒*/ | |||
| //request.setSlowRequestsThreshold(300000L); | |||
| /* 可指定每个分片慢请求时打印日志的时间阈值,默认为300s*/ | |||
| //request.setSlowRequestsThreshold(300000L); | |||
| /* 是否显示水印(可选),指定模板组ID时,根据模板组配置确定是否显示水印*/ | |||
| //request.setIsShowWaterMark(true); | |||
| /* 自定义消息回调设置(可选),参数说明参考文档 https://help.aliyun.com/document_detail/86952.html#UserData */ | |||
| // request.setUserData("{\"Extend\":{\"test\":\"www\",\"localId\":\"xxxx\"},\"MessageCallback\":{\"CallbackURL\":\"http://test.test.com\"}}"); | |||
| /* 视频分类ID(可选) */ | |||
| //request.setCateId(0); | |||
| /* 视频标签,多个用逗号分隔(可选) */ | |||
| //request.setTags("标签1,标签2"); | |||
| /* 视频描述(可选) */ | |||
| //request.setDescription("视频描述"); | |||
| /* 封面图片(可选) */ | |||
| //request.setCoverURL("http://cover.sample.com/sample.jpg"); | |||
| /* 模板组ID(可选) */ | |||
| //request.setTemplateGroupId("8c4792cbc8694e7084fd5330e56a33d"); | |||
| /* 工作流ID(可选) */ | |||
| //request.setWorkflowId("d4430d07361f0*be1339577859b0177b"); | |||
| /* 存储区域(可选) */ | |||
| //request.setStorageLocation("in-201703232118266-5sejdln9o.oss-cn-shanghai.aliyuncs.com"); | |||
| /* 开启默认上传进度回调 */ | |||
| request.setPrintProgress(true); | |||
| /* 设置自定义上传进度回调 (必须继承 VoDProgressListener) */ | |||
| request.setProgressListener(new PutObjectProgressListener()); | |||
| /* 设置您实现的生成STS信息的接口实现类*/ | |||
| // request.setVoDRefreshSTSTokenListener(new RefreshSTSTokenImpl()); | |||
| /* 设置应用ID*/ | |||
| //request.setAppId("app-1000000"); | |||
| /* 点播服务接入点 */ | |||
| request.setApiRegionId(regionId); | |||
| /* ECS部署区域*/ | |||
| request.setEcsRegionId(regionId); | |||
| UploadVideoImpl uploader = new UploadVideoImpl(); | |||
| UploadVideoResponse response = uploader.uploadVideo(request); | |||
| return response; | |||
| } | |||
| /** | |||
| * URL网络流上传。支持断点续传,最大支持48.8TB的单个文件。 | |||
| * 该上传方式需要先将网络文件下载到本地磁盘,再进行上传,所以要保证本地磁盘有充足的空间。 | |||
| * 当您设置的URL中不包括文件扩展名时,需要单独设置fileExtension,表示文件扩展名。 | |||
| * @param accessKeyId | |||
| * @param accessKeySecret | |||
| * @param title | |||
| * @param fileName | |||
| * @param url | |||
| */ | |||
| public static UploadURLStreamResponse uploadURLStream(String accessKeyId, String accessKeySecret,String regionId, String title, | |||
| String url, String fileExtension,RedisTemplate<String, Object> redisTemplate) { | |||
| UploadURLStreamRequest request = new UploadURLStreamRequest(accessKeyId, accessKeySecret, title, url); | |||
| /* 文件扩展名*/ | |||
| request.setFileExtension(fileExtension); | |||
| /* 网络文件下载连接超时,单位毫秒,0-表示不限制*/ | |||
| request.setDownloadConnectTimeout(1000); | |||
| /* 网络文件下载读取超时,单位毫秒,0-表示不限制*/ | |||
| request.setDownloadReadTimeout(0); | |||
| /* 网络文件下载后保存的本地目录*/ | |||
| request.setLocalDownloadFilePath("/aliyunvideo/download"); | |||
| /* 是否显示水印(可选),指定模板组ID时,根据模板组配置确定是否显示水印*/ | |||
| //request.setShowWaterMark(true); | |||
| /* 自定义消息回调设置(可选),参数说明参考文档 https://help.aliyun.com/document_detail/86952.html#UserData */ | |||
| // request.setUserData("{\"Extend\":{\"test\":\"www\",\"localId\":\"xxxx\"},\"MessageCallback\":{\"CallbackURL\":\"http://test.test.com\"}}"); | |||
| /* 视频分类ID(可选) */ | |||
| //request.setCateId(0); | |||
| /* 视频标签,多个用逗号分隔(可选) */ | |||
| //request.setTags("标签1,标签2"); | |||
| /* 视频描述(可选) */ | |||
| //request.setDescription("视频描述"); | |||
| /* 封面图片(可选) */ | |||
| //request.setCoverURL("http://cover.sample.com/sample.jpg"); | |||
| /* 模板组ID(可选) */ | |||
| //request.setTemplateGroupId("8c4792cbc8694e7084fd5330e56a33d"); | |||
| /* 工作流ID(可选) */ | |||
| //request.setWorkflowId("d4430d07361f0*be1339577859b0177b"); | |||
| /* 存储区域(可选) */ | |||
| //request.setStorageLocation("in-201703232118266-5sejdln9o.oss-cn-shanghai.aliyuncs.com"); | |||
| /* 开启默认上传进度回调 */ | |||
| request.setPrintProgress(true); | |||
| /* 设置自定义上传进度回调 (必须继承 VoDProgressListener) */ | |||
| request.setProgressListener(new PutObjectProgressListener()); | |||
| /* 设置应用ID*/ | |||
| //request.setAppId("app-1000000"); | |||
| /* 点播服务接入点 */ | |||
| request.setApiRegionId(regionId); | |||
| /* ECS部署区域*/ | |||
| request.setEcsRegionId(regionId); | |||
| UploadVideoImpl uploader = new UploadVideoImpl(); | |||
| UploadURLStreamResponse response = uploader.uploadURLStream(request); | |||
| return response; | |||
| } | |||
| /** | |||
| * 文件流上传接口 | |||
| * | |||
| * @param accessKeyId | |||
| * @param accessKeySecret | |||
| * @param title | |||
| * @param fileName | |||
| */ | |||
| private static void uploadFileStream(String accessKeyId, String accessKeySecret,String regionId, String title, String fileName, | |||
| RedisTemplate<String, Object> redisTemplate) { | |||
| UploadFileStreamRequest request = new UploadFileStreamRequest(accessKeyId, accessKeySecret, title, fileName); | |||
| /* 是否使用默认水印(可选),指定模板组ID时,根据模板组配置确定是否使用默认水印*/ | |||
| //request.setShowWaterMark(true); | |||
| /* 自定义消息回调设置,参数说明参考文档 https://help.aliyun.com/document_detail/86952.html#UserData */ | |||
| //request.setUserData(""{\"Extend\":{\"test\":\"www\",\"localId\":\"xxxx\"},\"MessageCallback\":{\"CallbackURL\":\"http://test.test.com\"}}""); | |||
| /* 视频分类ID(可选) */ | |||
| //request.setCateId(0); | |||
| /* 视频标签,多个用逗号分隔(可选) */ | |||
| //request.setTags("标签1,标签2"); | |||
| /* 视频描述(可选) */ | |||
| //request.setDescription("视频描述"); | |||
| /* 封面图片(可选) */ | |||
| //request.setCoverURL("http://cover.sample.com/sample.jpg"); | |||
| /* 模板组ID(可选) */ | |||
| //request.setTemplateGroupId("8c4792cbc8694e7084fd5330e56a33d"); | |||
| /* 工作流ID(可选) */ | |||
| //request.setWorkflowId("d4430d07361f0*be1339577859b0177b"); | |||
| /* 存储区域(可选) */ | |||
| //request.setStorageLocation("in-201703232118266-5sejdln9o.oss-cn-shanghai.aliyuncs.com"); | |||
| /* 开启默认上传进度回调 */ | |||
| request.setPrintProgress(true); | |||
| /* 设置自定义上传进度回调 (必须继承 VoDProgressListener) */ | |||
| request.setProgressListener(new PutObjectProgressListener()); | |||
| /* 设置应用ID*/ | |||
| //request.setAppId("app-1000000"); | |||
| /* 点播服务接入点 */ | |||
| request.setApiRegionId(regionId); | |||
| /* ECS部署区域*/ | |||
| request.setEcsRegionId(regionId); | |||
| UploadVideoImpl uploader = new UploadVideoImpl(); | |||
| UploadFileStreamResponse response = uploader.uploadFileStream(request); | |||
| System.out.print("RequestId=" + response.getRequestId() + "\n"); //请求视频点播服务的请求ID | |||
| if (response.isSuccess()) { | |||
| System.out.print("VideoId=" + response.getVideoId() + "\n"); | |||
| } else { | |||
| /* 如果设置回调URL无效,不影响视频上传,可以返回VideoId同时会返回错误码。其他情况上传失败时,VideoId为空,此时需要根据返回错误码分析具体错误原因 */ | |||
| System.out.print("VideoId=" + response.getVideoId() + "\n"); | |||
| System.out.print("ErrorCode=" + response.getCode() + "\n"); | |||
| System.out.print("ErrorMessage=" + response.getMessage() + "\n"); | |||
| } | |||
| } | |||
| /** | |||
| * 流式上传接口 | |||
| * | |||
| * @param accessKeyId | |||
| * @param accessKeySecret | |||
| * @param title | |||
| * @param fileName | |||
| * @param inputStream | |||
| */ | |||
| public static UploadStreamResponse uploadStream(String accessKeyId, String accessKeySecret,String regionId, String title, | |||
| String fileName, InputStream inputStream,RedisTemplate<String, Object> redisTemplate) { | |||
| UploadStreamRequest request = new UploadStreamRequest(accessKeyId, accessKeySecret, title, fileName, inputStream); | |||
| /* 是否使用默认水印(可选),指定模板组ID时,根据模板组配置确定是否使用默认水印*/ | |||
| //request.setShowWaterMark(true); | |||
| /* 自定义消息回调设置,参数说明参考文档 https://help.aliyun.com/document_detail/86952.html#UserData */ | |||
| //request.setUserData(""{\"Extend\":{\"test\":\"www\",\"localId\":\"xxxx\"},\"MessageCallback\":{\"CallbackURL\":\"http://test.test.com\"}}""); | |||
| /* 视频分类ID(可选) */ | |||
| //request.setCateId(0); | |||
| /* 视频标签,多个用逗号分隔(可选) */ | |||
| //request.setTags("标签1,标签2"); | |||
| /* 视频描述(可选) */ | |||
| //request.setDescription("视频描述"); | |||
| /* 封面图片(可选) */ | |||
| //request.setCoverURL("http://cover.sample.com/sample.jpg"); | |||
| /* 模板组ID(可选) */ | |||
| //request.setTemplateGroupId("8c4792cbc8694e7084fd5330e56a33d"); | |||
| /* 工作流ID(可选) */ | |||
| //request.setWorkflowId("d4430d07361f0*be1339577859b0177b"); | |||
| /* 存储区域(可选) */ | |||
| //request.setStorageLocation("in-201703232118266-5sejdln9o.oss-cn-shanghai.aliyuncs.com"); | |||
| /* 开启默认上传进度回调 */ | |||
| // request.setPrintProgress(true); | |||
| /* 设置自定义上传进度回调 (必须继承 VoDProgressListener) */ | |||
| // request.setProgressListener(new PutObjectProgressListener()); | |||
| /* 设置应用ID*/ | |||
| //request.setAppId("app-1000000"); | |||
| /* 点播服务接入点 */ | |||
| request.setApiRegionId(regionId); | |||
| /* ECS部署区域*/ | |||
| // request.setEcsRegionId(regionId); | |||
| UploadVideoImpl uploader = new UploadVideoImpl(); | |||
| UploadStreamResponse response = uploader.uploadStream(request); | |||
| return response; | |||
| } | |||
| /** | |||
| * 图片上传接口,本地文件上传示例 | |||
| * 参数参考文档 https://help.aliyun.com/document_detail/55619.html | |||
| * | |||
| * @param accessKeyId | |||
| * @param accessKeySecret | |||
| */ | |||
| public static void uploadImageLocalFile(String accessKeyId, String accessKeySecret,String regionId,RedisTemplate<String, Object> redisTemplate) { | |||
| /* 图片类型(必选)取值范围:default(默认),cover(封面),watermark(水印)*/ | |||
| String imageType = "cover"; | |||
| UploadImageRequest request = new UploadImageRequest(accessKeyId, accessKeySecret, imageType); | |||
| request.setImageType("cover"); | |||
| /* 图片文件扩展名(可选)取值范围:png,jpg,jpeg */ | |||
| //request.setImageExt("png"); | |||
| /* 图片标题(可选)长度不超过128个字节,UTF8编码 */ | |||
| //request.setTitle("图片标题"); | |||
| /* 图片标签(可选)单个标签不超过32字节,最多不超过16个标签,多个用逗号分隔,UTF8编码 */ | |||
| //request.setTags("标签1,标签2"); | |||
| /* 存储区域(可选)*/ | |||
| //request.setStorageLocation("out-4f3952f78c0211e8b3020013e7.oss-cn-shanghai.aliyuncs.com"); | |||
| /* 流式上传时,InputStream为必选,fileName为源文件名称,如:文件名称.png(可选)*/ | |||
| String fileName = "/Users/demo/png/test.png"; | |||
| request.setFileName(fileName); | |||
| /* 开启默认上传进度回调 */ | |||
| request.setPrintProgress(true); | |||
| /* 设置自定义上传进度回调 (必须继承 VoDProgressListener) */ | |||
| request.setProgressListener(new PutObjectProgressListener()); | |||
| /* 设置应用ID*/ | |||
| //request.setAppId("app-1000000"); | |||
| /* 点播服务接入点 */ | |||
| request.setApiRegionId(regionId); | |||
| UploadImageImpl uploadImage = new UploadImageImpl(); | |||
| UploadImageResponse response = uploadImage.upload(request); | |||
| System.out.print("RequestId=" + response.getRequestId() + "\n"); | |||
| if (response.isSuccess()) { | |||
| System.out.print("ImageId=" + response.getImageId() + "\n"); | |||
| System.out.print("ImageURL=" + response.getImageURL() + "\n"); | |||
| } else { | |||
| System.out.print("ErrorCode=" + response.getCode() + "\n"); | |||
| System.out.print("ErrorMessage=" + response.getMessage() + "\n"); | |||
| } | |||
| } | |||
| /** | |||
| * 图片上传接口,流式上传示例(支持文件流和网络流) | |||
| * 参数参考文档 https://help.aliyun.com/document_detail/55619.html | |||
| * | |||
| * @param accessKeyId | |||
| * @param accessKeySecret | |||
| */ | |||
| public static void uploadImageStream(String accessKeyId, String accessKeySecret,String regionId,RedisTemplate<String, Object> redisTemplate) { | |||
| /* 图片类型(必选)取值范围:default(默认),cover(封面),watermark(水印)*/ | |||
| String imageType = "cover"; | |||
| UploadImageRequest request = new UploadImageRequest(accessKeyId, accessKeySecret, imageType); | |||
| /* 图片文件扩展名(可选)取值范围:png,jpg,jpeg */ | |||
| //request.setImageExt("png"); | |||
| /* 图片标题(可选)长度不超过128个字节,UTF8编码 */ | |||
| //request.setTitle("图片标题"); | |||
| /* 图片标签(可选)单个标签不超过32字节,最多不超过16个标签,多个用逗号分隔,UTF8编码 */ | |||
| //request.setTags("标签1,标签2"); | |||
| /* 存储区域(可选)*/ | |||
| //request.setStorageLocation("out-4f3952f78c0211e8b3020013e7.oss-cn-shanghai.aliyuncs.com"); | |||
| /* 流式上传时,InputStream为必选,fileName为源文件名称,如:文件名称.png(可选)*/ | |||
| //request.setFileName("测试文件名称.png"); | |||
| /* 开启默认上传进度回调 */ | |||
| request.setPrintProgress(true); | |||
| /* 设置自定义上传进度回调 (必须继承 VoDProgressListener) */ | |||
| request.setProgressListener(new PutObjectProgressListener()); | |||
| /* 设置应用ID*/ | |||
| //request.setAppId("app-1000000"); | |||
| // 1.文件流上传 | |||
| // InputStream fileStream = getFileStream(request.getFileName()); | |||
| // if (fileStream != null) { | |||
| // request.setInputStream(fileStream); | |||
| // } | |||
| // 2.网络流上传 | |||
| String url = "http://test.aliyun.com/image/default/test.png"; | |||
| InputStream urlStream = getUrlStream(url); | |||
| if (urlStream != null) { | |||
| request.setInputStream(urlStream); | |||
| } | |||
| // 开始上传图片 | |||
| UploadImageImpl uploadImage = new UploadImageImpl(); | |||
| UploadImageResponse response = uploadImage.upload(request); | |||
| System.out.print("RequestId=" + response.getRequestId() + "\n"); | |||
| if (response.isSuccess()) { | |||
| System.out.print("ImageId=" + response.getImageId() + "\n"); | |||
| System.out.print("ImageURL=" + response.getImageURL() + "\n"); | |||
| } else { | |||
| System.out.print("ErrorCode=" + response.getCode() + "\n"); | |||
| System.out.print("ErrorMessage=" + response.getMessage() + "\n"); | |||
| } | |||
| } | |||
| /** | |||
| * 上传本地m3u8视频或音频文件到点播,m3u8文件和分片文件默认在同一目录(sliceFilenames为空时,会按照同一目录去解析分片地址) | |||
| * | |||
| * @param request 本地m3u8上传请求类 | |||
| * m3u8Filename: 本地m3u8索引文件的绝对路径,且m3u8文件的分片信息必须是相对路径,不能含有URL或本地绝对路径 | |||
| * sliceFilenames: ts分片文件的绝对路径列表,如指定则以此为准,若不指定,则自动解析 m3u8Filename 里的m3u8文件 | |||
| */ | |||
| public static void uploadLocalM3u8(String accessKeyId, String accessKeySecret,String regionId) { | |||
| String title = "test_upload_local_m3u8"; | |||
| String m3u8Filename = "/Users/test/0e9ecfc6da934d1887ed7bdfc925ecf5/cc38da35c7b24de0abe58619cdd7a8-6479a12446b994719838e0307f6458-ld.m3u8"; | |||
| UploadLocalM3u8Request request = new UploadLocalM3u8Request(accessKeyId, accessKeySecret, title, m3u8Filename); | |||
| String[] sliceFilenames = new String[]{ | |||
| "/Users/test/0e9ecfc6da934d1887ed7bdfc925ecf5/slices/cc38da35c7b24de0abe58619cdd7a896-c45797a1ad6e75fbb9d1a84937034742-ld-00001.ts", | |||
| "/Users/test/0e9ecfc6da934d1887ed7bdfc925ecf5/slices/cc38da35c7b24de0abe58619cdd7a896-c45797a1ad6e75fbb9d1a84937034742-ld-00002.ts", | |||
| "/Users/test/0e9ecfc6da934d1887ed7bdfc925ecf5/slices/cc38da35c7b24de0abe58619cdd7a896-c45797a1ad6e75fbb9d1a84937034742-ld-00003.ts", | |||
| "/Users/test/0e9ecfc6da934d1887ed7bdfc925ecf5/slices/cc38da35c7b24de0abe58619cdd7a896-c45797a1ad6e75fbb9d1a84937034742-ld-00004.ts", | |||
| "/Users/test/0e9ecfc6da934d1887ed7bdfc925ecf5/slices/cc38da35c7b24de0abe58619cdd7a896-c45797a1ad6e75fbb9d1a84937034742-ld-00005.ts" | |||
| }; | |||
| // ts分片文件列表,可选,不指定时,直接解析m3u8FileURL获取分片地址 | |||
| request.setSliceFilenames(sliceFilenames); | |||
| /* 可指定分片上传时每个分片的大小,默认为2M字节 */ | |||
| request.setPartSize(2 * 1024 * 1024L); | |||
| /* 可指定分片上传时的并发线程数,默认为1,(注:该配置会占用服务器CPU资源,需根据服务器情况指定)*/ | |||
| request.setTaskNum(1); | |||
| /* 是否显示水印(可选),指定模板组ID时,根据模板组配置确定是否显示水印*/ | |||
| //request.getShowWaterMark(true); | |||
| /* 自定义消息回调设置(可选),参数说明参考文档 https://help.aliyun.com/document_detail/86952.html#UserData */ | |||
| // request.setUserData("{\"Extend\":{\"test\":\"www\",\"localId\":\"xxxx\"},\"MessageCallback\":{\"CallbackURL\":\"http://test.test.com\"}}"); | |||
| /* 视频分类ID(可选) */ | |||
| //request.setCateId(-1L); | |||
| /* 视频标签,多个用逗号分隔(可选) */ | |||
| //request.setTags("标签1,标签2"); | |||
| /* 视频描述(可选) */ | |||
| //request.setDescription("视频描述"); | |||
| /* 封面图片(可选) */ | |||
| //request.setCoverURL("http://cover.sample.com/sample.jpg"); | |||
| /* 模板组ID(可选) */ | |||
| //request.setTemplateGroupId("8c4792cbc8694e7084fd5330e56a33d"); | |||
| /* 工作流ID(可选) */ | |||
| //request.setWorkflowId("d4430d07361f0*be1339577859b0177b"); | |||
| /* 存储区域(可选) */ | |||
| //request.setStorageLocation("in-201703232118266-5sejdln9o.oss-cn-shanghai.aliyuncs.com"); | |||
| /* 设置应用ID*/ | |||
| // request.setAppId("app-1000000"); | |||
| /* 点播服务接入点 */ | |||
| request.setApiRegionId(regionId); | |||
| /* ECS部署区域*/ | |||
| request.setEcsRegionId(regionId); | |||
| UploadM3u8FileImpl uploadM3u8File = new UploadM3u8FileImpl(); | |||
| UploadLocalM3u8Response uploadLocalM3u8Response = uploadM3u8File.uploadLocalM3u8(request); | |||
| System.out.println("code = " + uploadLocalM3u8Response.getCode()); | |||
| System.out.println("message = " + uploadLocalM3u8Response.getMessage()); | |||
| System.out.println("videoId = " + uploadLocalM3u8Response.getVideoId()); | |||
| System.out.println("requestId = " + uploadLocalM3u8Response.getRequestId()); | |||
| } | |||
| /** | |||
| * 上传网络m3u8视频或音频文件到点播,需本地磁盘空间足够,会先下载到本地临时目录,再上传到点播存储 | |||
| * | |||
| * @param request 网络m3u8上传请求类 | |||
| * m3u8FileURL: 网络m3u8索引文件的URL地址,且m3u8文件的分片信息必须是相对地址,不能含有URL或本地绝对路径 | |||
| * sliceFileURLs: ts分片文件的URL地址列表;需自行拼接ts分片的URL地址列表 | |||
| */ | |||
| public static void uploadWebM3u8(String accessKeyId, String accessKeySecret,String regionId) { | |||
| String title = "test_upload_web_m3u8"; | |||
| String m3u8FileURL = "http://test.aliyun.com/f0d644abc547129e957b386f772c72/a0e1e2817ab9425aa558fe67a90e717f-538087dcf2c201c31ce4324bf76af691-ld.m3u8"; | |||
| UploadWebM3u8Request request = new UploadWebM3u8Request(accessKeyId, accessKeySecret, title, m3u8FileURL); | |||
| String[] sliceFileURLs = new String[]{ | |||
| "http://test.aliyun.com/f0d644abc547129e957b386f772c72/a0e1e2817ab9425aa558fe67a90e717f-822598b9c170a8c6dad985e20cd9c27d-ld-00001.ts", | |||
| "http://test.aliyun.com/f0d644abc547129e957b386f772c72/a0e1e2817ab9425aa558fe67a90e717f-822598b9c170a8c6dad985e20cd9c27d-ld-00002.ts", | |||
| "http://test.aliyun.com/f0d644abc547129e957b386f772c72/a0e1e2817ab9425aa558fe67a90e717f-822598b9c170a8c6dad985e20cd9c27d-ld-00003.ts", | |||
| "http://test.aliyun.com/f0d644abc547129e957b386f772c72/a0e1e2817ab9425aa558fe67a90e717f-822598b9c170a8c6dad985e20cd9c27d-ld-00004.ts", | |||
| "http://test.aliyun.com/f0d644abc547129e957b386f772c72/a0e1e2817ab9425aa558fe67a90e717f-822598b9c170a8c6dad985e20cd9c27d-ld-00005.ts" | |||
| }; | |||
| // ts分片地址,可选,不指定时,直接解析m3u8FileURL获取分片地址 | |||
| request.setSliceFileURLs(sliceFileURLs); | |||
| /* 下载文件的临时存储目录,可自定义,如不指定则保存到程序所运行的目录下*/ | |||
| // request.setGlobalLocalFilePath("/User/download/"); | |||
| /* 可指定分片上传时每个分片的大小,默认为2M字节 */ | |||
| request.setPartSize(2 * 1024 * 1024L); | |||
| /* 可指定分片上传时的并发线程数,默认为1,(注:该配置会占用服务器CPU资源,需根据服务器情况指定)*/ | |||
| request.setTaskNum(1); | |||
| /* 是否显示水印(可选),指定模板组ID时,根据模板组配置确定是否显示水印*/ | |||
| //request.setShowWaterMark(true); | |||
| /* 自定义消息回调设置(可选),参数说明参考文档 https://help.aliyun.com/document_detail/86952.html#UserData */ | |||
| //request.setUserData("{\"Extend\":{\"test\":\"www\",\"localId\":\"xxxx\"},\"MessageCallback\":{\"CallbackURL\":\"http://test.test.com\"}}"); | |||
| /* 视频分类ID(可选) */ | |||
| //request.setCateId(-1L); | |||
| /* 视频标签,多个用逗号分隔(可选) */ | |||
| //request.setTags("标签1,标签2"); | |||
| /* 视频描述(可选) */ | |||
| //request.setDescription("视频描述"); | |||
| /* 封面图片(可选) */ | |||
| //request.setCoverURL("http://cover.sample.com/sample.jpg"); | |||
| /* 模板组ID(可选) */ | |||
| //request.setTemplateGroupId("8c4792cbc8694e7084fd5330e56a33d"); | |||
| /* 工作流ID(可选) */ | |||
| //request.setWorkflowId("d4430d07361f0*be1339577859b0177b"); | |||
| /* 存储区域(可选) */ | |||
| //request.setStorageLocation("in-201703232118266-5sejdln9o.oss-cn-shanghai.aliyuncs.com"); | |||
| /* 设置应用ID*/ | |||
| //request.setAppId("app-1000000"); | |||
| /* 点播服务接入点 */ | |||
| request.setApiRegionId(regionId); | |||
| /* ECS部署区域*/ | |||
| request.setEcsRegionId(regionId); | |||
| UploadM3u8FileImpl uploadM3u8File = new UploadM3u8FileImpl(); | |||
| UploadWebM3u8Response uploadWebM3u8Response = uploadM3u8File.uploadWebM3u8(request); | |||
| System.out.println("code = " + uploadWebM3u8Response.getCode()); | |||
| System.out.println("message = " + uploadWebM3u8Response.getMessage()); | |||
| System.out.println("videoId = " + uploadWebM3u8Response.getVideoId()); | |||
| System.out.println("requestId = " + uploadWebM3u8Response.getRequestId()); | |||
| } | |||
| /** | |||
| * 辅助媒资上传接口,本地文件上传示例 | |||
| * 参数参考文档 https://help.aliyun.com/document_detail/98467.html | |||
| * | |||
| * @param accessKeyId | |||
| * @param accessKeySecret | |||
| */ | |||
| public static void uploadAttachedMediaLocalFile(String accessKeyId, String accessKeySecret,String regionId) { | |||
| /* 业务类型 */ | |||
| String businessType = "watermark"; | |||
| /* 文件扩展名 */ | |||
| String mediaExt = "png"; | |||
| String filename = "/Users/demo/png/test.png"; | |||
| UploadAttachedMediaRequest request = new UploadAttachedMediaRequest(accessKeyId, accessKeySecret, businessType, mediaExt); | |||
| request.setFileName(filename); | |||
| /* 标题*/ | |||
| request.setTitle("test_attached_media"); | |||
| /* 分类ID */ | |||
| request.setCateId(-1L); | |||
| /* 标签,多个用逗号分隔(可选) */ | |||
| request.setTags("tag1,tag2"); | |||
| /* 描述(可选) */ | |||
| request.setDescription("test_desc"); | |||
| /* 存储区域(可选) */ | |||
| request.setStorageLocation("out-20170323225118266-5l3hs5gqwa.oss-cn-shanghai.aliyuncs.com"); | |||
| /* 点播服务接入点 */ | |||
| request.setApiRegionId(regionId); | |||
| /* 设置应用ID*/ | |||
| //request.setAppId("app-1000000"); | |||
| UploadAttachedMediaImpl uploader = new UploadAttachedMediaImpl(); | |||
| UploadAttachedMediaResponse response = uploader.upload(request); | |||
| System.out.print("RequestId=" + response.getRequestId() + "\n"); | |||
| if (response.isSuccess()) { | |||
| System.out.print("MediaId=" + response.getMediaId() + "\n"); | |||
| System.out.print("MediaURL=" + response.getMediaURL() + "\n"); | |||
| System.out.print("FileURL=" + response.getFileURL() + "\n"); | |||
| } else { | |||
| System.out.print("ErrorCode=" + response.getCode() + "\n"); | |||
| System.out.print("ErrorMessage=" + response.getMessage() + "\n"); | |||
| } | |||
| } | |||
| /** | |||
| * 辅助媒资上传接口,流式上传示例(支持文件流和网络流) | |||
| * 参数参考文档 https://help.aliyun.com/document_detail/98467.html | |||
| * | |||
| * @param accessKeyId | |||
| * @param accessKeySecret | |||
| */ | |||
| public static void uploadAttachedMediaStream(String accessKeyId, String accessKeySecret,String regionId) { | |||
| /* 业务类型 */ | |||
| String businessType = "watermark"; | |||
| /* 文件扩展名 */ | |||
| String mediaExt = "png"; | |||
| String filename = "http://test.aliyun.com/test.png"; | |||
| UploadAttachedMediaRequest request; | |||
| // 1.文件流上传 | |||
| InputStream fileStream = getFileStream(filename); | |||
| request = new UploadAttachedMediaRequest(accessKeyId, accessKeySecret, businessType, mediaExt); | |||
| request.setInputStream(fileStream); | |||
| // 2.网络流上传 | |||
| // String url = "http://test.aliyun.com/image//test.png"; | |||
| // InputStream urlStream = getUrlStream(url); | |||
| // request = new UploadAttachedMediaRequest(accessKeyId, accessKeySecret, businessType, mediaExt); | |||
| // request.setInputStream(urlStream); | |||
| /* 标题*/ | |||
| request.setTitle("test_attached_media"); | |||
| /* 分类ID */ | |||
| request.setCateId(-1L); | |||
| /* 标签,多个用逗号分隔(可选) */ | |||
| request.setTags("tag1,tag2"); | |||
| /* 描述(可选) */ | |||
| request.setDescription("test_desc"); | |||
| /* 存储区域(可选) */ | |||
| request.setStorageLocation("out-20170323225118266-5l3****wa.oss-cn-shanghai.aliyuncs.com"); | |||
| /* 点播服务接入点 */ | |||
| request.setApiRegionId(regionId); | |||
| /* 设置应用ID*/ | |||
| // request.setAppId("app-1000000"); | |||
| // 开始上传 | |||
| UploadAttachedMediaImpl uploader = new UploadAttachedMediaImpl(); | |||
| UploadAttachedMediaResponse response = uploader.upload(request); | |||
| System.out.print("RequestId=" + response.getRequestId() + "\n"); | |||
| if (response.isSuccess()) { | |||
| System.out.print("MediaId=" + response.getMediaId() + "\n"); | |||
| System.out.print("MediaURL=" + response.getMediaURL() + "\n"); | |||
| System.out.print("FileURL=" + response.getFileURL() + "\n"); | |||
| } else { | |||
| System.out.print("ErrorCode=" + response.getCode() + "\n"); | |||
| System.out.print("ErrorMessage=" + response.getMessage() + "\n"); | |||
| } | |||
| } | |||
| private static InputStream getFileStream(String fileName) { | |||
| try { | |||
| return new FileInputStream(fileName); | |||
| } catch (FileNotFoundException e) { | |||
| e.printStackTrace(); | |||
| } | |||
| return null; | |||
| } | |||
| private static InputStream getUrlStream(String url) { | |||
| try { | |||
| return new URL(url).openStream(); | |||
| } catch (IOException e) { | |||
| e.printStackTrace(); | |||
| } | |||
| return null; | |||
| } | |||
| public static String getUploadProgress(RedisTemplate<String, Object> redisTemplate,String videoId) { | |||
| return UploadCacheHelper.getUploadProgress(redisTemplate, PutObjectProgressListener.PRE_VIDEO_PROGRESS+videoId); | |||
| } | |||
| } | |||
| @@ -1,131 +0,0 @@ | |||
| package com.iformall.video.aliyun.sdk.upload; | |||
| import org.springframework.data.redis.core.RedisTemplate; | |||
| import com.aliyun.oss.event.ProgressEvent; | |||
| import com.aliyun.oss.event.ProgressEventType; | |||
| import com.aliyun.vod.upload.impl.VoDProgressListener; | |||
| /** | |||
| * 上传进度回调方法类 | |||
| * 当您开启上传进度回调时该事件回调才会生效。 | |||
| * OSS分片上传成功或失败均触发相应的回调事件,您可根据业务逻辑处理相应的事件回调。 | |||
| * 当创建音视频信息成功后,此上传进度回调中的videoId为本次上传生成的视频ID,您可以根据视频ID进行音视频管理。 | |||
| * 当创建图片信息成功后,此上传进度回调中的ImageId为本次上传生成的图片ID,您可以根据视频ID进行图片管理。 | |||
| */ | |||
| public class PutObjectProgressListener implements VoDProgressListener { | |||
| /** | |||
| * 已成功上传至OSS的字节数 | |||
| */ | |||
| private long bytesWritten = 0; | |||
| /** | |||
| * 原始文件的总字节数 | |||
| */ | |||
| private long totalBytes = -1; | |||
| /** | |||
| * 本次上传成功标记 | |||
| */ | |||
| private boolean succeed = false; | |||
| /** | |||
| * 视频ID | |||
| */ | |||
| private String videoId; | |||
| /** | |||
| * 图片ID | |||
| */ | |||
| private String imageId; | |||
| public static final String PRE_VIDEO_PROGRESS = "video:progress:"; | |||
| private RedisTemplate<String, Object> redisTemplate; | |||
| public void progressChanged(ProgressEvent progressEvent) { | |||
| long bytes = progressEvent.getBytes(); | |||
| ProgressEventType eventType = progressEvent.getEventType(); | |||
| switch (eventType) { | |||
| // 开始上传事件 | |||
| case TRANSFER_STARTED_EVENT: | |||
| if (null != redisTemplate) { | |||
| if (videoId != null) { | |||
| UploadCacheHelper.cacheStart(redisTemplate, PRE_VIDEO_PROGRESS+videoId); | |||
| //System.out.println("qqqqStart to upload videoId " + videoId + "......"); | |||
| } | |||
| if (imageId != null) { | |||
| //System.out.println("aaaStart 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 + ")"); | |||
| } else { | |||
| //System.out.println(bytes + " bytes have been written at this time, upload sub total : " + | |||
| // "(" + this.bytesWritten + ")"); | |||
| } | |||
| UploadCacheHelper.cacheProgress(redisTemplate, PRE_VIDEO_PROGRESS+videoId,String.valueOf(this.bytesWritten)); | |||
| break; | |||
| // 文件全部上传成功事件通知 | |||
| case TRANSFER_COMPLETED_EVENT: | |||
| this.succeed = true; | |||
| if (videoId != null) { | |||
| UploadCacheHelper.cacheComplete(redisTemplate, PRE_VIDEO_PROGRESS+videoId); | |||
| //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) { | |||
| UploadCacheHelper.cacheProgress(redisTemplate, PRE_VIDEO_PROGRESS+videoId,String.valueOf(this.bytesWritten)); | |||
| 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 boolean isSucceed() { | |||
| return succeed; | |||
| } | |||
| public void onVidReady(String videoId) { | |||
| setVideoId(videoId); | |||
| } | |||
| 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; | |||
| } | |||
| } | |||
| @@ -1,37 +0,0 @@ | |||
| package com.iformall.video.aliyun.sdk.upload; | |||
| import java.util.concurrent.TimeUnit; | |||
| import org.springframework.data.redis.core.RedisTemplate; | |||
| import org.springframework.data.redis.core.ValueOperations; | |||
| public class UploadCacheHelper { | |||
| public static void cacheStart(RedisTemplate<String, Object> template,String key) { | |||
| ValueOperations<String, Object> operations = template.opsForValue(); | |||
| operations.set(key, "begin", 24*3600,TimeUnit.SECONDS); | |||
| } | |||
| public static void cacheComplete(RedisTemplate<String, Object> template,String key) { | |||
| ValueOperations<String, Object> operations = template.opsForValue(); | |||
| operations.set(key, "complete", 24*3600,TimeUnit.SECONDS); | |||
| } | |||
| public static void cacheProgress(RedisTemplate<String, Object> template,String key,String bytes) { | |||
| ValueOperations<String, Object> operations = template.opsForValue(); | |||
| operations.set(key, bytes, 24*3600,TimeUnit.SECONDS); | |||
| } | |||
| public static String getUploadProgress(RedisTemplate<String, Object> template,String key) { | |||
| if (template.hasKey(key)) { | |||
| ValueOperations<String, Object> operations = template.opsForValue(); | |||
| Object o = operations.get(key); | |||
| if (o instanceof String) { | |||
| return (String)o; | |||
| } | |||
| } | |||
| return null; | |||
| } | |||
| } | |||
| @@ -0,0 +1,50 @@ | |||
| package com.iformall.video.aliyun.thread; | |||
| import org.springframework.context.annotation.Bean; | |||
| import org.springframework.context.annotation.Configuration; | |||
| import org.springframework.core.task.AsyncTaskExecutor; | |||
| import org.springframework.scheduling.annotation.EnableAsync; | |||
| import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; | |||
| import com.iformall.video.aliyun.config.AliyunVideoConfig; | |||
| import lombok.Data; | |||
| import java.util.concurrent.Executor; | |||
| import java.util.concurrent.ThreadPoolExecutor; | |||
| import org.springframework.beans.factory.annotation.Value; | |||
| import org.springframework.boot.context.properties.ConfigurationProperties; | |||
| @Data | |||
| @Configuration | |||
| @EnableAsync | |||
| @ConfigurationProperties(prefix = "video.aliyun") | |||
| public class AliyunVedioThreadExecutorConfig { | |||
| private int corePoolSize; | |||
| private int maxPoolSize; | |||
| private int queueCapacity; | |||
| private String namePrefix; | |||
| @Bean(name = "asyncVideoServiceExecutor") | |||
| public Executor asyncVideoServiceExecutor() { | |||
| ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor(); | |||
| //配置核心线程数 | |||
| executor.setCorePoolSize(corePoolSize); | |||
| //配置最大线程数 | |||
| executor.setMaxPoolSize(maxPoolSize); | |||
| //配置队列大小 | |||
| executor.setQueueCapacity(queueCapacity); | |||
| //配置线程池中的线程的名称前缀 | |||
| executor.setThreadNamePrefix(namePrefix); | |||
| // rejection-policy:当pool已经达到max size的时候,如何处理新任务 | |||
| // CALLER_RUNS:不在新线程中执行任务,而是有调用者所在的线程来执行 | |||
| executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy()); | |||
| //执行初始化 | |||
| executor.initialize(); | |||
| return executor; | |||
| } | |||
| } | |||
| @@ -0,0 +1,32 @@ | |||
| package com.iformall.video.aliyun.thread; | |||
| import org.springframework.stereotype.Service; | |||
| import com.aliyuncs.vod.model.v20170321.CreateUploadVideoResponse; | |||
| import com.iformall.video.aliyun.sdk.server.AliyunVedioServer; | |||
| import com.iformall.video.aliyun.sdk.server.UploadCacheHelper; | |||
| import lombok.extern.slf4j.Slf4j; | |||
| import java.io.InputStream; | |||
| import java.io.UnsupportedEncodingException; | |||
| import org.springframework.data.redis.core.RedisTemplate; | |||
| import org.springframework.scheduling.annotation.Async; | |||
| //https://blog.csdn.net/m0_37701381/article/details/81072774 | |||
| @Service | |||
| @Slf4j | |||
| public class AliyunVideoUploadThread { | |||
| @Async("asyncVideoServiceExecutor") | |||
| public void executeAysncTask(CreateUploadVideoResponse response,String localFile,RedisTemplate<String, Object> redisTemplate) throws InterruptedException { | |||
| try { | |||
| AliyunVedioServer.uploadVideo(response, localFile,redisTemplate); | |||
| } catch (UnsupportedEncodingException e) { | |||
| log.error("AliyunVideoUploadThread upload error."+response.getVideoId(),e); | |||
| UploadCacheHelper.cacheError(redisTemplate, response.getVideoId()); | |||
| } | |||
| } | |||
| } | |||
| @@ -156,11 +156,6 @@ | |||
| <artifactId>rocketmq-spring-boot-starter</artifactId> | |||
| <version>1.0.0.RELEASE</version> | |||
| </dependency> | |||
| <dependency> | |||
| <groupId>org.apache.rocketmq</groupId> | |||
| <artifactId>rocketmq-client</artifactId> | |||
| <version>4.4.0</version> | |||
| </dependency> | |||
| <dependency> | |||
| <groupId>org.apache.commons</groupId> | |||