1. 程式人生 > 實用技巧 >視訊分片上傳,斷點續傳

視訊分片上傳,斷點續傳

樣式

      <div class="body-inner">
        <div class="input_contant" style="display: block;margin-bottom: 10px;">
          <label id="realBtn" class="btn btn-info">
            <input name="file" id="videos" type="file" accept="video/*" @change="selectOtherVideo(this)"
              style
="left:-9999px;position:absolute;"> <span style="width: 100%;display: inline-block;"><i class="el-icon-video-camera"></i> 視訊上傳( ≤1GB )</span> </label> </div> <div class="upload-content-span"> // 進度條 <div id="upload-progress"> <el-progress :percentage="percent" color="#67c23a" id='progress'></el-progress> </div> //
上傳成功後顯示內容 <div id="preview_course_video_text"></div> <div id="upload-video-status">上傳成功</div> <div id="upload-progress-text"> 上傳速度取決於您的網速,請耐心等待... <!--<span class="upload-progress-cancel">取消上傳</span> --> </div> </div> </div>

js上傳

selectOtherVideo() {
      var c = document.getElementById('upload-video-status')
      var d = document.getElementById('upload-progress-text')
      var e = document.getElementById('upload-progress')
      var f = document.getElementById('preview_course_video_text')

      c.style.display = 'none'
      d.style.display = 'none'
      f.style.display = 'none'
      this.beginUploadVideo()
    },
    // 分片上傳
    beginUploadVideo() {
      this.submFlag = true;
      var fileName = ""
      var videoUrl = ""
      if (!document.all) {  // IE11,Chrome,FF
        var files = document.getElementById('videos').files;
        // console.log(files, 'files');
        if (files.length == 0) {
          alert("請先上傳視訊!")
          return false;
        } else if (files[0].size > (1024 * 1024 * 1024)) {
          alert('視訊大小不能大於1GB')
          return false;
        }
        fileName = files[0].name
        videoUrl = files[0]
      } else {
        // IE10
        if (!isIE9()) {
          if (!FileReader.prototype.readAsBinaryString) {
            var files = document.getElementById('videos').files[0];
            fileName = files.name
            videoUrl = files
            if (files.size > (1024 * 1024 * 1024)) {
              alert('視訊大小不能大於1GB')
              return false;
            }
          }
        }
      }
      document.getElementById('videos').disabled = true
      document.getElementById('upload-progress').style.display = 'block'
      var blockSize = 8 * 1024 * 1024;//每塊的大小
      // console.log(videoUrl, blockSize)
      // console.log(Math.ceil(videoUrl.size / blockSize))
      var count = Math.ceil(videoUrl.size / blockSize) // 總塊數
      this.readChunk(videoUrl, count, blockSize)
    },
    getChunkInfo(file, currentChunk, chunkSize) {
      let start = currentChunk * chunkSize
      let end = Math.min(file.size, start + chunkSize)
      let chunk = file.slice(start, end)
      // console.log(start, end, chunk)
      return { start, end, chunk }
    },
    // 針對每個檔案進行chunk處理
    readChunk(file, chunkCount, chunkSize) {
      // 針對單個檔案進行chunk上傳
      // console.log(file, chunkCount, chunkSize)
      let i = 0
      let uuid = ''
      let offset = 0
      let complete = false
      this.uploadChunk({ file, uuid, offset, complete, chunkCount, currentChunk: i, chunkSize })
      // }
    },
    uploadChunk(chunkInfo) {
      // console.log(chunkInfo)
      var data = {
        uuid: chunkInfo.uuid,
        offset: chunkInfo.offset,
        complete: chunkInfo.chunkCount == 1 ? true : chunkInfo.complete
      }
      // console.log("總片數" + chunkInfo.chunkCount)
      // console.log("第" + chunkInfo.currentChunk + '分片')
      var { chunk, start, end } = this.getChunkInfo(chunkInfo.file, chunkInfo.currentChunk, chunkInfo.chunkSize)
      var fileData = new window.File([chunkInfo.file.slice(start, end)], chunkInfo.file.name, { type: chunkInfo.file.type })
      // console.log(fileData, start, end, '擷取。。。。。。。。。。。。。。。。。')
      this.percent = Math.floor((chunkInfo.currentChunk / chunkInfo.chunkCount) * 100)
      document.getElementById('progress').style.width = '190px'
      getFragmentationUploadUrl(data).then(res => {
        if (res.code == 200) {
          sessionStorage.setItem('uuid', res.data.uuid)
          var formData = new FormData();//初始化一個FormData物件
          formData.append("file", fileData);//將 部分檔案 塞入FormData
          document.getElementById('upload-progress-text').style.display = 'block'
          document.getElementById('upload-progress').style.display = 'block'
          axios.request({
            url: res.data.url, /*設定post提交到的頁面*/
            method: "post", /*設定表單以post方法提交*/
            data: formData,
            headers: {
              token: getToken()
            },
            // responseType: "blob",
            //使用XMLHttpRequest.upload監聽上傳過程,註冊progress事件,列印回撥函式中的event事件
            onDownloadProgress(progress) {
              // console.log(progress, '++++++++++++++++++++++++++')
              // var progressRate = (chunkInfo.currentChunk / chunkInfo.chunkCount) * 100
              document.getElementById('progress').style.width = '190px'
              this.percent = Math.floor((progress.loaded / progress.total) / chunkInfo.chunkCount * 100 + (chunkInfo.currentChunk / chunkInfo.chunkCount) * 100)
            }
          }).then(res => {
            // console.log(res);
            let data = res.data
            if (data.code == 1) {
              // console.log(101010);
              let list = chunkInfo
              list.currentChunk += 1
              // console.log("第" + list.currentChunk + '張上傳成功+++++++++++++')
              if (list.currentChunk == list.chunkCount) {
                this.percent = 100
                document.getElementById('progress').style.width = '100%'
                // console.log('停+++++++++++++')
                document.getElementById('videos').disabled = false
                document.getElementById("preview_course_video_text").innerHTML = '視訊ID:' + data.resultObject.archiveId
                document.getElementById("preview_course_video_text").style.display = 'block'
                document.getElementById('upload-progress-text').style.display = 'none'
                document.getElementById('upload-video-status').style.color = '#1ea725'
                document.getElementById('upload-video-status').style.display = 'none'
                this.$message({ type: "success", message: "上傳成功!" });
                this.ruleForm.archiveId = data.resultObject.archiveId;
                this.ruleForm.duration = data.resultObject.duration;
                this.ruleForm.fileSize = parseInt(data.resultObject.fileSize);
                this.submFlag = false;
                document.getElementById('videos').value = ''
                return false
              }
             // created 定義stop:0 
             // 取消時  stop=1  中斷上傳
              if (this.stop == 1) {
                this.$message({ type: "warning", message: "已取消上傳!" })
                document.getElementById('videos').value = ''
                document.getElementById('videos').disabled = false
                return false
              }
              // console.log("不停--------------")
              list.offset = data.resultObject.offset
              list.uuid = sessionStorage.getItem('uuid')
              if (list.currentChunk == list.chunkCount - 1) {
                list.complete = true
              } else {
                list.complete = false
              }
              this.uploadChunk(list)
            } else {
              document.getElementById('videos').disabled = false
              document.getElementById('videos').value = ''
              document.getElementById('upload-video-status').innerHTML = "上傳失敗"
              document.getElementById('upload-video-status').style.color = '#ff0000'
              document.getElementById('upload-video-status').style.display = 'block'
              document.getElementById('upload-progress-text').style.display = 'none'
              this.submFlag = false;
              let list = chunkInfo
              list.offset = start
              // console.log(list, '繼續上傳')
              sessionStorage.setItem('chunkList', JSON.stringify(list))
            }
          }).catch(error => {
            document.getElementById('videos').disabled = false
            document.getElementById('videos').value = ''
            document.getElementById('upload-progress-text').style.display = 'none'
            document.getElementById('upload-video-status').innerHTML = "上傳失敗"
            document.getElementById('upload-video-status').style.color = '#ff0000'
            document.getElementById('upload-video-status').style.display = 'block'
            this.submFlag = false;
            let list = chunkInfo
            list.offset = start
            // console.log(list, '繼續上傳')
            sessionStorage.setItem('chunkList', JSON.stringify(list))
          })
        } else {
          console.log(res.msg);
        }
      }).catch(err => {
        console.log(err);
      })
    },
 //  繼續上傳失敗的部分
   goOnUploadVideo() {
     var files = document.getElementById('videos').files[0];
     var list = JSON.parse(sessionStorage.getItem('chunkList'))
      console.log(files, list, '繼續');
      list.uuid = sessionStorage.getItem('uuid')
      list.file = files
       this.uploadChunk(list)
     },

jQuery上傳

// 分片上傳
// 開始上傳視訊
function beginUploadVideo() {
    var fileName = ""
    var videoUrl = ""
    if (!document.all) {  // IE11,Chrome,FF
        var files = document.getElementById('videos').files;
        if (files.length == 0) {
            alert("請先上傳視訊!")
            return false;
        } else if (files[0].size > (1024 * 1024 * 1024)) {
            alert('視訊大小不能大於1GB')
            return false;
        }
        fileName = files[0].name
        videoUrl = files[0]
    } else {
        // IE10
        if (!isIE9()) {
            if (!FileReader.prototype.readAsBinaryString) {
                var files = document.getElementById('videos').files[0];
                fileName = files.name
                videoUrl = files
                if (files.size > (1024 * 1024 * 1024)) {
                    alert('視訊大小不能大於1GB')
                    return false;
                }
            }
        }
    }
    var blockSize = 8 * 1024 * 1024;//每塊的大小
    // console.log(videoUrl, blockSize)
    // console.log(Math.ceil(videoUrl.size / blockSize))
    var count = Math.ceil(videoUrl.size / blockSize) // 總塊數
    readChunk(videoUrl, count, blockSize)
}
function getChunkInfo(file, currentChunk, chunkSize) {
    // console.log('2222222222--------------')
    let start = currentChunk * chunkSize
    let end = Math.min(file.size, start + chunkSize)
    let chunk = file.slice(start, end)
    // console.log(start, end, chunk)
    return { start, end, chunk }
}
// 針對每個檔案進行chunk處理
function readChunk(file, chunkCount, chunkSize) {
    // console.log('11111111--------------')
    // 針對單個檔案進行chunk上傳
    // console.log(file, chunkCount, chunkSize)
    let i = 0
    let uuid = ''
    let offset = 0
    let complete = false
    uploadChunk({ file, uuid, offset, complete, chunkCount, currentChunk: i, chunkSize })
    // }
}

// 獲取建學唐上傳視訊地址
function uploadChunk(chunkInfo) {
    // console.log('3333333--------------')
    // console.log(chunkInfo)
    var data = {
        uuid: chunkInfo.uuid,
        offset: chunkInfo.offset,
        complete: chunkInfo.chunkCount == 1 ? true : chunkInfo.complete
    }
    // console.log("總片數" + chunkInfo.chunkCount)
    // console.log("第" + chunkInfo.currentChunk + '分片')
    var { chunk, start, end } = getChunkInfo(chunkInfo.file, chunkInfo.currentChunk, chunkInfo.chunkSize)
    var fileData = new window.File([chunkInfo.file.slice(start, end)], chunkInfo.file.name, { type: chunkInfo.file.type })
    // console.log(fileData, start, end, '擷取。。。。。。。。。。。。。。。。。')
    var percent = (chunkInfo.currentChunk / chunkInfo.chunkCount) * 100
    $('.upload-progress-inner').css('width', percent + '%');
    $.ajax({
        // 介面,
        url: 介面,
        type: "POST",
        cache: false,
        data: JSON.stringify(data),
        headers: {
            token: sessionStorage.getItem("HXKToken")
        },
        processData: false,
        contentType: "application/json",
        dataType: "json",
        success: function (res) {
            // console.log("分片上傳返回資訊:")
            // console.log(res.data.url, res.data.uuid, chunkInfo.offset)
            if (res.code == 200) {
                // sessionStorage.setItem('VideoUploadUrl', res.data.url)
                sessionStorage.setItem('uuid', res.data.uuid)
                $("#submitVideoButton").removeAttr("disabled")
                // var apiUrl = sessionStorage.getItem('VideoUploadUrl')
                // var uuid = sessionStorage.getItem('uuid')
                var formData = new FormData();//初始化一個FormData物件
                formData.append("file", fileData);//將 部分檔案 塞入FormData
                // formData.append("uuid", res.data.uuid);//儲存檔名字
                // formData.append("offset", chunkInfo.offset);//儲存檔名字
                // formData.append("complete", chunkInfo.complete);//儲存檔名字
                // console.log(formData)
                $(".upload-video-status").text("視訊上傳中...").css({
                    "display": "block",
                    "color": "#069af0",
                })
                $(".upload-progress-text").css({ "display": "block" });
                $(".upload-progress").css({ "display": "block" });
                $("#submitVideoButton").attr("disabled", 'disabled'); // 禁掉提交按鈕
                $.ajax({
                    url: res.data.url, /*設定post提交到的頁面*/
                    type: "post", /*設定表單以post方法提交*/
                    cache: false,
                    data: formData,
                    dataType: "json", /*設定返回值型別為文字*/
                    headers: {
                        token: sessionStorage.getItem("HXKToken")
                    },
                    processData: false,
                    contentType: false,  // 告訴jQuery不要去設定Content-Type請求頭
                    xhr: function () { // 增加 progress 事件繫結
                        $("#videos").attr("disabled", "disabled")   // 禁掉選擇視訊按鈕
                        $(".upload-progress-inner").css("background", "#07c160"); // 把上傳條調轉為綠色
                        var xhr = new XMLHttpRequest();
                        //使用XMLHttpRequest.upload監聽上傳過程,註冊progress事件,列印回撥函式中的event事件
                        xhr.upload.addEventListener('progress', function (e) {
                            // console.log(e, '++++++++++++++++++++++++++')
                            // var progressRate = (chunkInfo.currentChunk / chunkInfo.chunkCount) * 100
                            var progressRate = (e.loaded / e.total) / chunkInfo.chunkCount * 100 + (chunkInfo.currentChunk / chunkInfo.chunkCount) * 100
                            // var realProgress = progressRate == 100 ? 98 : progressRate;
                            //通過設定進度條的寬度達到效果
                            $('.upload-progress-inner').css('width', progressRate + '%');
                        })
                        return xhr;
                    },
                    success: function (data) {
                        if (data.code == 1) {
                            // console.log(data, '上傳成功返回資料--------------------')
                            // $('.upload-progress-inner').css('width', '100%');
                            $("#video_archiveId").text(data.resultObject.archiveId)
                            $("#video_fileSize").text(data.resultObject.fileSize)
                            $("#video_duration").text(data.resultObject.duration)
                            let list = chunkInfo
                            list.currentChunk += 1
                            // console.log(list.currentChunk, list.chunkCount)
                            // console.log("第" + list.currentChunk + '張上傳成功+++++++++++++')
                            if (list.currentChunk == list.chunkCount) {
                                // console.log('停+++++++++++++')
                                $("#videos").removeAttr("disabled")
                                $("#preview_course_video_text").text("視訊ID:" + data.resultObject.archiveId)
                                $(".upload-progress-text").css({ "display": "none" });
                                $(".upload-video-status").text("上傳成功").css({
                                    "display": "block",
                                    "color": "#1ea725",
                                });
                                $("#submitVideoButton").val("已上傳")
                                $('#submitVideoButton').css({ 'display': 'inline-block' })
                                $('#goOnVideoButton').css({ 'display': 'none' })
                                $("#submitVideoButton").attr("disabled", "disabled")
                                return false
                            }
                            // console.log("不停--------------")
                            list.offset = data.resultObject.offset
                            list.uuid = sessionStorage.getItem('uuid')
                            // console.log(data.resultObject.offset, list)
                            if (list.currentChunk == list.chunkCount - 1) {
                                list.complete = true
                            } else {
                                list.complete = false
                            }
                            // console.log($("#submitVideoButton").val())
                            uploadChunk(list)
                        } else {
                            $(".upload-progress-inner").css("background", "#ff0000") // 把上傳條調轉為紅色
                            $('#submitVideoButton').css({ 'display': 'none' })
                            $('#goOnVideoButton').css({ 'display': 'inline-block' })
                            $("#goOnVideoButton").removeAttr("disabled")
                            $(".upload-video-status").text("上傳失敗").css({
                                "display": "block",
                                "color": "#ff0000",
                            });
                            // alert(data.msg)
                            // console.log($("#submitVideoButton").val())
                            let list = chunkInfo
                            list.offset = start
                            // list.uuid = sessionStorage.getItem('uuid')
                            // console.log(list, '繼續上傳')
                            sessionStorage.setItem('chunkList', JSON.stringify(list))
                        }
                    },
                    error: function (error) {
                        $("#videos").removeAttr("disabled")
                        $('#submitVideoButton').removeAttr("disabled");
                        $(".upload-progress-inner").css({ "background": "#ff0000" }); // 把上傳條調轉為紅色
                        $(".upload-progress-text").css({ "display": "none" });
                        $('#submitVideoButton').css({ 'display': 'none' })
                        $('#goOnVideoButton').css({ 'display': 'inline-block' })
                        $("#goOnVideoButton").removeAttr("disabled")
                        $(".upload-video-status").text("上傳失敗").css({
                            "display": "block",
                            "color": "#ff0000",
                        });
                        // alert(error.responseJSON.msg);
                        // console.log($("#submitVideoButton").val())
                        let list = chunkInfo
                        list.offset = start
                        // list.uuid = sessionStorage.getItem('uuid')
                        // console.log(list, '繼續上傳')
                        sessionStorage.setItem('chunkList', JSON.stringify(list))
                    },
                });
            } else {
                $("#submitVideoButton").removeAttr("disabled")
                alert(res.msg);
            }
        },
        error: function (err) {
            $("#submitVideoButton").removeAttr("disabled")
            alert("獲取上傳視訊地址失敗!")
        }
    })
}

function goOnUploadVideo() {
    var files = document.getElementById('videos').files[0];
    var list = JSON.parse(sessionStorage.getItem('chunkList'))
    list.uuid = sessionStorage.getItem('uuid')
    list.file = files
    uploadChunk(list)
    $("#goOnVideoButton").attr("disabled", "disabled")
}