当前位置: 首页 > news >正文

uniapp开发app 上传视频切片上传

<u-toast ref="uploadFileToast">
	<view style="font-weight: bold;font-size: 30rpx;">正在上传视频</view>
	<view>当前进度 {{curUploadVideoProgress}}%</view>
</u-toast>

js部分

uni.chooseVideo({
   count: this.videoMaxCount,
    // compressed: this.platform == 'ios' ? false : true, //苹果不压缩  压缩会导致苹果视频 变横屏
    compressed: false, 
    pageOrientation:'auto',
    camera: this.cameraList[this.cameraIndex].value, //'front'、'back',默认'back'
    sourceType: ['album', 'camera'],
    success: async e => {
      console.log('原文件视频e: ', e);
      uni.getVideoInfo({
        src:e.tempFilePath,
        success:async (detailedInformation) => {
          console.log('视频详细信息detailedInformation: ', detailedInformation);
          that.uploadVideoChunks(e, detailedInformation ,(r) => {
            that.videoList = [];
            that.videoList = [r]
          });
        }
      })
      // this.fileVideo(e)
    },
    fail: (fail) => {

      console.log('上传失败', fail)

      that.showManualAuth('android.permission.CAMERA');
    },
    complete: () => {
      try {
        plus.navigator.setFullscreen(false)
      } catch (error) {
      }
    }
  }),
  // 负责将视频文件分片并发上传
     async uploadVideoChunks(e,detailedInformation,callBack) {
      if (e.size > 300 * 1024 * 1024) {
        uni.showToast({
          title: '视频过大,请您上传300Mb以内视频',
          icon: 'none',
          duration: 2000
        });
        return
      }
      let that = this
      const filePath = e.tempFilePath;
      const fileSize = e.size;
      const CHUNK_SIZE = 1024 * 1024 * 10; // 每个分片的大小,这里设置为5MB
      const totalChunks = Math.ceil(fileSize / CHUNK_SIZE); // 总切片数
      const extension  = filePath.substring(filePath.lastIndexOf('/') + 1).split('.').pop();
      const fileName = `${this.randomString(10)+ new Date().getTime()}.${extension}`; // 视频文件名
      console.log('视频文件名: ', fileName);
      const chunkPromises = [];
      const chunkProgresses = new Array(totalChunks).fill(0);// 用于存储每个分片的上传进度
      for (let chunkIndex = 0; chunkIndex < totalChunks; chunkIndex++) {
        const start = chunkIndex * CHUNK_SIZE;
        const end = Math.min(start + CHUNK_SIZE, fileSize);
        const chunk = await this.sliceFile(filePath, start, end);
        console.log('chunk: ', chunk);
        
        const uploadPromise =  this.uploadChunk(chunk, fileName, chunkIndex, totalChunks , (progress) => {
          // 更新当前分片的进度
          chunkProgresses[chunkIndex] = progress;
          // 计算总的上传进度
          const totalProgress = chunkProgresses.reduce((sum, current) => sum + current, 0) / totalChunks;
          this.curUploadVideoProgress = Math.round(totalProgress);
          // console.log(`当前上传进度: ${that.curUploadVideoProgress}%`);
        });
        chunkPromises.push(uploadPromise);
      }

      try {
        that.$refs.uploadFileToast.show({
          type: 'loading',
          title: '',
          message: "",
          iconUrl: 'https://cdn.uviewui.com/uview/demo/toast/loading.png',
          duration: 999999
        })
        let ressss =  await Promise.all(chunkPromises);
        that.$refs.uploadFileToast.hide()
        uni.showLoading({
          mask: true,
          title: '视频处理中,请稍等...'
        })
        this.curUploadVideoProgress = 0;
        console.log('ressss: ', ressss);
        let params = {
          name: fileName,
          chunks: totalChunks,
          merge: 1
        }
        // 通知服务器合并分片并压缩处理
        console.log('通知服务器合并分片params: ', params);
        this.$circleApi.uploadfile(params).then(result => {
          console.log('视频所有分片上传完成',result);
          let params = {
            url: result.url,
            file_class: result.file_class,
            mimetype: detailedInformation.type,
            filesize: result.filesize || 0,
            width: result.width || 0,
            height: result.height || 0,
          }
          console.log('保存数据库params: ', params);
          // 保存数据库
          this.$circleApi.postCircleDynamicSavefiles(params).then((resPCDSF) => {
            console.log('保存数据库成功resPCDSF: ', resPCDSF);
            let r = {
              url: result.vedio_url,
              id: resPCDSF.files_id
            }
            uni.hideLoading();
            callBack(r)
          }).catch(err => {
            uni.$u.toast("文件上传失败");
            uni.hideLoading();
            console.log('err: ', err);
          })
        }).catch(err => {
          uni.$u.toast("文件上传失败");
          that.$refs.uploadFileToast.hide()
          console.log('err: ', err);
        })
      } catch (error) {
        console.error('分片上传过程中出现错误:', error);
        uni.$u.toast("文件上传失败");
        that.$refs.uploadFileToast.hide()
      }
    },
    // 从视频文件中截取指定范围的分片。
    async sliceFile(filePath, start, end) {
      return new Promise((resolve, reject) => {
        // 将相对路径转换为绝对路径
        const absolutePath = plus.io.convertLocalFileSystemURL(filePath);
        plus.io.resolveLocalFileSystemURL(absolutePath, function (entry) {
          entry.file(function (file) {
            const blob = file.slice(start, end);
            resolve(blob);
          }, function (e) {
            reject(e);
          });
        }, function (e) {
          reject(e);
        });
      });
    },
    // 将单个分片上传到服务器
    async uploadChunk(chunk, fileName, chunkIndex, totalChunks , onProgress) {
      console.log(`开始上传第 ${chunkIndex + 1} 个分片,共 ${totalChunks} 个分片`)
      const token = 'Bearer ' + this.userInfo.token
      let platform = uni.getSystemInfoSync().platform
      let types = 'Android'
      if (platform === 'ios') {
        types = 'iOS'
      } else if (platform === 'android') {
        types = 'Android'
      } else {
        types = 'llkj'
      }
      return new Promise((resolve, reject) => {
        const uploadTask = uni.uploadFile({
          url: base.baseUrl + '/circle/dynamic/multiUpload', // 替换为实际的上传接口地址
          filePath: chunk.fullPath,
          name: 'file',
          header:{
            "Content-Type": "multipart/form-data",
            'Authorization': token,
            'Api-Client': types,
          },
          formData: {
            name: fileName,
            chunk: chunkIndex,
            chunks: totalChunks,
          },
          success: (res) => {
            resolve(res)
            console.log('上传结果res: ', res);
          },
          fail: (err) => {
            reject(err);
          }
        });
        uploadTask.onProgressUpdate((res) => {
          const progress = res.progress;
          if (onProgress) {
            onProgress(progress);
          }
        });
      });
    },
	}
   

相关文章:

  • 基于51单片机的智能停车场proteus仿真
  • IM基本设计思路与有序ID的重要性
  • 关税核爆72小时!跨境矩阵防御战紧急打响
  • ACF导电粒子聚集问题阐述及依据聚集位置制定规避措施
  • 生物化学笔记:医学免疫学原理12 黏膜免疫系统 + 抗原性物质含片(“糖丸”的原理)免疫调节
  • 1g内存电脑sqlite能支持多少并发
  • Android Java 实现事件总线
  • 【ubuntu24.04】挂载windows的共享文件夹
  • 软件工程面试题(二十二)
  • # 使用 Dlib 和 OpenCV 实现人脸关键点检测
  • CTF类题目复现总结-hashcat 1
  • 推理场景的存力范式迁移
  • AI本地部署之ragflow
  • Educational Codeforces Round 172 (Rated for Div. 2)
  • ros2--gazebo--launch
  • Ubuntu离线安装mysql
  • 处理JWT Token失效需求
  • Debezium日常分享系列之:Debezium3.1版本之增量快照
  • 通过 Markdown 改进 RAG 文档处理
  • 1ms软延时,不用定时器,stm32