赞
踩
记录我惨痛的阿里云视频点播批量上传教训~~(Javascript SDK 上传)
阿里的点播视频上传官方文档是很精简,也有案例,无奈我这个渣渣看了官方文档始终不理解它的内部机制。看了好多案例,自己捣鼓了无数遍,今天下午终于成功了。
1.首先,我要总结一下我一开始不理解的批量上传:
官方文档中给我们提供了一个uploader.addFile函数,这个函数的作用是将我们在input选择框中一次性选中的多个视频文件添加到视频点播实例化对象=>uploader的上传列表中。
然后,我们通过自己设置的一个button触发uploader的startUpload(开始上传)事件。重点来了:
触发startUpload事件后,进入了文档列举的onUploadstarted状态中,在这里我们通过uploadInfo 获取到视频文件列表中第一个文件的file,file.name, 通过判断当前的文件的videoId是否存在,去确定是否要重新获取视频上传凭证。
视频上传凭证获取成功以后,就会自动进入到 onUploadProgress、onUploadSucceed或者其他状态进程中。
当视频列表中的第一个视频文件上传成功后,uploader会自动选中下一个视频文件进行上传。当视频列表的所有文件上传成功以后,会进入到onUploadEnd状态进程中,表明列表中所有文件上传成功。
(原来通过控制台打印,我始终只能看到一个视频文件,而不是文件列表,我还一直在纠结怎么在第一个文件上传成功以后去上传第二个视频文件,甚至还傻乎乎的去触发了第二次startUpload,结果就是直接提示xxx is experied-->进程已经开始或者过期);
2. 第二个坑:通过addFile添加文件到列表成功,点击按钮触发startUpload事件,在onUploadstarted触发后台获取视频上传凭证接口并拿到了uploadAuth, uploadAdress,并进行设置。 但是,死活都不显示进入onProgress中的上传百分比。
代码如下:
- onUploadstarted: function (uploadInfo) {
- //获取文件上传列表
- that.uploader.listFiles();
- var list = that.uploader.listFiles();
- for (var i=0; i<list.length; i++) {
- console.log("file:" + list[i].file.name + ", status:" + list[i].state + ", endpoint:" + list[i].endpoint + ", bucket:" + list[i].bucket + ", object:" + list[i].object);
- }
-
- if (!uploadInfo.videoId) {
- var fileName = uploadInfo.file.name
- var title = that.title
- //后台获取视频上传凭证接口
-
- that.auth(fileName, title)
- that.uploader.setUploadAuthAndAddress(uploadInfo, that.uploadAuth, that.uploadAddress, that.videoId );
- console.log("onUploadStarted:" + uploadInfo.file.name + ", uploadAuth:" + uploadInfo.uploadAuth + ", uploadAddress:" + uploadInfo.uploadAddress
- + ", endpoint:" + uploadInfo.endpoint + ", bucket:" + uploadInfo.bucket + ", object:" + uploadInfo.object)
- } else {
-
- var fileName = uploadInfo.file.name
- var title = that.title
- //获取视频上传凭证
- that.auth(fileName, title)
- console.log("onUploadStarted:" + uploadInfo.file.name + ", uploadAuth:" + uploadInfo.uploadAuth + ", uploadAddress:" + uploadInfo.uploadAddress
- + ", endpoint:" + uploadInfo.endpoint + ", bucket:" + uploadInfo.bucket + ", object:" + uploadInfo.object)
- }
- },
获取视频上传凭证方法(后端接口获取,得到的结果是uploadAuth、uploadAddress、videoId)
- auth(fileName, title){
- let param = new FormData()
- param.append("file_name",fileName)
- param.append("title",title)
- param.append("types", 1) //接口必传参数
- this.$http.post("back/get_ali_video_token/", param).then((response)=>{
- console.log("返回的数据", response.data.data)
- this.uploadAuth = response.data.data.UploadAuth;
- this.uploadAddress = response.data.data.UploadAddress;
- this.videoId = response.data.data.VideoId;
- }).catch(function(error){
- console.log(error);
- })
- },
无论是将 setUploadAuthAndAddress(uploadInfo, that.uploadAuth, that.uploadAddress, that.videoId )写在auth方法中还是写在 onUploadstarted方法中,都无法正常进入 onUploadProgress中,通过控制台数据打印,发现
console.log("返回的数据", response.data.data) //打印从后端获取到的uploadAuth、uploadAdress等信息
在 setUploadAuthAndAddress后出现了,我感觉应该是异步执行的问题,证明uploadAuth、uploadAddress、videoId还是没有设置到uploader中,所以才导致上传失败。
3. 解决方法:直接把auth方法中的内容抽出放在onUploadstarted中:
- onUploadstarted: function (uploadInfo) {
- // 如果是 UploadAuth 上传方式, 需要调用 uploader.setUploadAuthAndAddress 方法
- // 如果是 UploadAuth 上传方式, 需要根据 uploadInfo.videoId是否有值,调用点播的不同接口获取uploadauth和uploadAddress
- // 如果 uploadInfo.videoId 有值,调用刷新视频上传凭证接口,否则调用创建视频上传凭证接口
- // 注意: 这里是测试 demo 所以直接调用了获取 UploadAuth 的测试接口, 用户在使用时需要判断 uploadInfo.videoId 存在与否从而调用 openApi
- // 如果 uploadInfo.videoId 存在, 调用 刷新视频上传凭证接口(https://help.aliyun.com/document_detail/55408.html)
- // 如果 uploadInfo.videoId 不存在,调用 获取视频上传地址和凭证接口(https://help.aliyun.com/document_detail/55407.html)
-
- //获取文件上传列表
- that.uploader.listFiles();
- var list = that.uploader.listFiles();
- for (var i=0; i<list.length; i++) {
- console.log("file:" + list[i].file.name + ", status:" + list[i].state + ", endpoint:" + list[i].endpoint + ", bucket:" + list[i].bucket + ", object:" + list[i].object);
- }
-
- if (!uploadInfo.videoId) {
- var fileName = uploadInfo.file.name
- var title = that.title
- //获取上传凭证和地址
- let param = new FormData()
- param.append("file_name",fileName)
- param.append("title",title)
- // param.append("types", 1)
- that.$http.post("back/get_ali_video_token/",param
- ).then((response)=>{
- console.log("返回信息", response)
- let uploadAuth = response.data.data.UploadAuth;
- let uploadAddress = response.data.data.UploadAddress;
- let videoId = response.data.data.VideoId;
- that.uploader.setUploadAuthAndAddress(uploadInfo, uploadAuth, uploadAddress, videoId)
- }).catch(function(error){
- console.log(error);
- })
- console.log("onUploadStarted:" + uploadInfo.file.name + ", uploadAuth:" + uploadInfo.uploadAuth + ", uploadAddress:" + uploadInfo.uploadAddress
- + ", endpoint:" + uploadInfo.endpoint + ", bucket:" + uploadInfo.bucket + ", object:" + uploadInfo.object)
- } else {
- /*
- // 如果videoId有值,根据videoId刷新上传凭证
- var refreshUrl = 'https://localhost:44325/vod/IRefreshUploadVideo?videoId=' + uploadInfo.videoId
- var fileName = uploadInfo.file.name
- //自定义上传接口
- //afaf8aa3d3e2489fb55a5601f076d3d1这里会莫名多出一个id,由于时间问题,所以这边我直接调用了视频接口,没有调用刷新凭证接口
- var createUrl = 'https://localhost:44325/vod/ICreateUploadVideo?title=' + fileName + '&fileName=' + fileName
- $.get(createUrl, function (data) {
- var uploadAuth = data.uploadAuth
- var uploadAddress = data.uploadAddress
- var videoId = data.videoId
- uploader.setUploadAuthAndAddress(uploadInfo, uploadAuth, uploadAddress, videoId)
- }, 'json')
- */
- var fileName = uploadInfo.file.name
- var title = that.title
- //获取上传凭证和地址
- let param = new FormData()
- param.append("file_name",fileName)
- param.append("title",title)
- //param.append("types", 1) //该接口需要传的参数
- that.$http.post("back/get_ali_video_token/",param
- ).then((response)=>{
- console.log("返回信息", response)
- let uploadAuth = response.data.data.UploadAuth;
- let uploadAddress = response.data.data.UploadAddress;
- let videoId = response.data.data.VideoId;
- that.uploader.setUploadAuthAndAddress(uploadInfo, uploadAuth, uploadAddress, videoId)
- }).catch(function(error){
- console.log(error);
- })
- console.log("onUploadStarted:" + uploadInfo.file.name + ", uploadAuth:" + uploadInfo.uploadAuth + ", uploadAddress:" + uploadInfo.uploadAddress
- + ", endpoint:" + uploadInfo.endpoint + ", bucket:" + uploadInfo.bucket + ", object:" + uploadInfo.object)
- }
- },
这样便可以正确的将当前视频文件的上传凭证等信息正确设置了,上传进程也能够正确进行了。
4. 还有一个小提示,当前上传进程开始后,我们应该禁用触发startUpload事件的按钮,避免上传报错的发生~~
以下是完整代码(使用结构是Vue):
(1)上传视频入口
- <el-dialog title="视频上传" :visible.sync="createVideoChange(控制该窗口的显示)" :close-on-click-modal="false">
- 视频上传:
- <input type="file" multiple accept=".mp4" ref="clearFile" id="files" @change="triggerFile($event)"/>
- <el-button size="small" type="primary" style="margin:10px 0 0 0;" @click="uploadVideo" :disabled="onPro">开始上传</el-button><br/>
- {{this.file}}<el-progress :stroke-width="2" :percentage="this.progressNum" style="margin-top:5px; width: 500px;"></el-progress>
- <br />
- <br />
-
- <span slot="footer">
- <el-button @click="closeUploadVideo">取 消</el-button>
- <el-button type="primary" @click="closeUploadVideo">确定</el-button>
- </span>
- </el-dialog>
(2)相关参数
- data(){
- return {
- uploader: null, //点播实例
- progressNum: 0, //进度条
- file: '', //当前上传的文件名
- uploadAuth: '', //点播信息
- uploadAddress: '',
- videoId: '',
- }
- }
(3)选择视频文件
- triggerFile(event){
- this.efile = event
- console.log("文件上传列表", this.efile)
- //开始上传视频
- this.startUploadVideo(event)
- },
-
- //开始上传视频
- startUploadVideo(file){
- if(!file){
- return this.$message.warning("选择需要上传的视频!")
- }
-
- var userData = '{"Vod":{}}'
-
- //当前已经存在uploader 则暂停上传
- if(this.uploader){
- this.uploader.stopUpload()
- this.progressNum = 0;
- }
-
- //初始化实例 不存在uploader实例就要初始化
- this.uploader = this.Origin()
-
- // 首先调用 uploader.addFile(event.target.files[i], null, null, null, userData)
- //批量添加文件上传 标题为素材id+时间戳+当前视频id
- for (var i = 0; i < file.target.files.length; i++) {
- this.uploader.addFile(file.target.files[i], null, null, null, userData)
- //上传标题名为文件名
- this.title = this.materialId + '-' + file.target.files[i].name
- }
-
- },
(4)创建点播实例
- Origin() {
- let that = this
- var uploader = new AliyunUpload.Vod({
- timeout: 90000,
- partSize: 1048576,
- parallel: that.efile.target.files.length,//文件多少,就设置多少
- retryCount: 3,
- retryDuration: 2,
- region: '',
- userId: that.userId,
- // 添加文件成功
- addFileSuccess: function (uploadInfo) {
- console.log('addFileSuccess', uploadInfo)
- console.log("添加文件名addFileSuccess: " + uploadInfo.file.name)
- },
-
- onUploadstarted: function (uploadInfo) {
- // 如果是 UploadAuth 上传方式, 需要调用 uploader.setUploadAuthAndAddress 方法
- // 如果是 UploadAuth 上传方式, 需要根据 uploadInfo.videoId是否有值,调用点播的不同接口获取uploadauth和uploadAddress
- // 如果 uploadInfo.videoId 有值,调用刷新视频上传凭证接口,否则调用创建视频上传凭证接口
- // 注意: 这里是测试 demo 所以直接调用了获取 UploadAuth 的测试接口, 用户在使用时需要判断 uploadInfo.videoId 存在与否从而调用 openApi
- // 如果 uploadInfo.videoId 存在, 调用 刷新视频上传凭证接口(https://help.aliyun.com/document_detail/55408.html)
- // 如果 uploadInfo.videoId 不存在,调用 获取视频上传地址和凭证接口(https://help.aliyun.com/document_detail/55407.html)
-
- //获取文件上传列表
- that.uploader.listFiles();
- var list = that.uploader.listFiles();
- for (var i=0; i<list.length; i++) {
- console.log("file:" + list[i].file.name + ", status:" + list[i].state + ", endpoint:" + list[i].endpoint + ", bucket:" + list[i].bucket + ", object:" + list[i].object);
- }
-
- if (!uploadInfo.videoId) {
- var fileName = uploadInfo.file.name
- var title = that.title
- //获取上传凭证和地址
- let param = new FormData()
- param.append("file_name",fileName)
- param.append("title",title)
- param.append("types", 1) //创客代理
- that.$http.post("back/get_ali_video_token/",param
- ).then((response)=>{
- console.log("返回信息", response)
- let uploadAuth = response.data.data.UploadAuth;
- let uploadAddress = response.data.data.UploadAddress;
- let videoId = response.data.data.VideoId;
- that.uploader.setUploadAuthAndAddress(uploadInfo, uploadAuth, uploadAddress, videoId)
- }).catch(function(error){
- console.log(error);
- })
- console.log("onUploadStarted:" + uploadInfo.file.name + ", uploadAuth:" + uploadInfo.uploadAuth + ", uploadAddress:" + uploadInfo.uploadAddress
- + ", endpoint:" + uploadInfo.endpoint + ", bucket:" + uploadInfo.bucket + ", object:" + uploadInfo.object)
- } else {
- /*
- // 如果videoId有值,根据videoId刷新上传凭证
- var refreshUrl = 'https://localhost:44325/vod/IRefreshUploadVideo?videoId=' + uploadInfo.videoId
- var fileName = uploadInfo.file.name
- //自定义上传接口
- //afaf8aa3d3e2489fb55a5601f076d3d1这里会莫名多出一个id,由于时间问题,所以这边我直接调用了视频接口,没有调用刷新凭证接口
- var createUrl = 'https://localhost:44325/vod/ICreateUploadVideo?title=' + fileName + '&fileName=' + fileName
- $.get(createUrl, function (data) {
- var uploadAuth = data.uploadAuth
- var uploadAddress = data.uploadAddress
- var videoId = data.videoId
- uploader.setUploadAuthAndAddress(uploadInfo, uploadAuth, uploadAddress, videoId)
- }, 'json')
- */
- var fileName = uploadInfo.file.name
- var title = that.title
- //获取上传凭证和地址
- let param = new FormData()
- param.append("file_name",fileName)
- param.append("title",title)
- param.append("types", 1) //创客代理
- that.$http.post("back/get_ali_video_token/",param
- ).then((response)=>{
- console.log("返回信息", response)
- let uploadAuth = response.data.data.UploadAuth;
- let uploadAddress = response.data.data.UploadAddress;
- let videoId = response.data.data.VideoId;
- that.uploader.setUploadAuthAndAddress(uploadInfo, uploadAuth, uploadAddress, videoId)
- }).catch(function(error){
- console.log(error);
- })
- console.log("onUploadStarted:" + uploadInfo.file.name + ", uploadAuth:" + uploadInfo.uploadAuth + ", uploadAddress:" + uploadInfo.uploadAddress
- + ", endpoint:" + uploadInfo.endpoint + ", bucket:" + uploadInfo.bucket + ", object:" + uploadInfo.object)
- }
- },
- // 文件上传成功
- onUploadSucceed: function (uploadInfo) {
- // that.$message.success(uploadInfo.file.name+ "上传成功!两分钟内自动上线")
- console.log("文件1上传成功的videoID", uploadInfo.videoId)
- that.file = uploadInfo.file.name
- that.video_id = uploadInfo.videoId
- that.createVideo()
- console.log("onUploadSucceed: " + uploadInfo.file.name + ", endpoint:" + uploadInfo.endpoint + ", bucket:" + uploadInfo.bucket + ", object:" + uploadInfo.object)
- },
- // 文件上传失败
- onUploadFailed: function (uploadInfo, code, message) {
- that.$message.error(uploadInfo.file.name + "上传失败,请从当前视频开始重新上传")
- console.log("onUploadFailed: file:" + uploadInfo.file.name + ",code:" + code + ", message:" + message)
- },
- // 取消文件上传
- onUploadCanceled: function (uploadInfo, code, message) {
- console.log("Canceled file: " + uploadInfo.file.name + ", code: " + code + ", message:" + message)
- },
- // 文件上传进度,单位:字节, 可以在这个函数中拿到上传进度并显示在页面上
- onUploadProgress: function (uploadInfo, totalSize, progress) {
- that.onPro = true
- console.log("正在上传中")
- that.file = uploadInfo.file.name
- that.progressNum = (progress * 100).toFixed(2)
- console.log("onUploadProgress:file:" + uploadInfo.file.name + ", fileSize:" + totalSize + ", percent:" + Math.ceil(progress * 100) + "%")
- },
- // 上传凭证超时
- onUploadTokenExpired: function (uploadInfo) {
- // 上传大文件超时, 如果是上传方式一即根据 UploadAuth 上传时
- // 需要根据 uploadInfo.videoId 调用刷新视频上传凭证接口(https://help.aliyun.com/document_detail/55408.html)重新获取 UploadAuth
- // 然后调用 resumeUploadWithAuth 方法, 这里是测试接口, 所以我直接获取了 UploadAuth
- console.log('文件上传超时!')
-
- },
- // 全部文件上传结束
- onUploadEnd: function (uploadInfo) {
- console.log("onUploadEnd: uploaded all the files")
- that.$message.success("所有视频上传成功!")
- }
- })
- return uploader
- },
(5)点击按钮开始上传视频
- //tt 确认视频上传按钮 标题和文件名不为空 初始化进程
- uploadVideo(){
- //点击上传视频,实例不为空 则开始上传
- if(this.uploader !== null){
- this.uploader.startUpload();
- }
- },
视频点播,虽然官方文档描述真的挺清晰的,但是理解存在偏差就要钻牛角尖了,而且还没那么容易出来~~~~
在此需要感谢@孤独wind小白博主写的文章,从他那里我得到很多启发,原文链接:
https://www.jianshu.com/p/eb0b9c92ee71
感谢查看我的文章,可能描述的不是那么清晰,欢迎提出意见或者进行交流,共同进步,感谢
果然还是CSDN的编辑器给力~~用起来舒服
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。