小程序分片上传

//去选取视频,然后根据视频来判断需要不需要进行剪辑功能,如果进入剪辑,iOS不显示视频时间,安卓显示,所以如果有时长限制可以直接用参数来设置最小时长和最大时长
goVideo = (index) => {
    this.pauseVideo()
    const { houseMaterialInfo } = this.state
    let houseInfo = houseMaterialInfo
    this.setState({ upLoadingIndex: index })
    wx.chooseMedia({
      sourceType: ['album'],
      mediaType: ['video'],
      count: 1,
      sizeType: ['original'],
      success: res => {
        if (res.tempFiles[0].size > (500 * 1024 * 1024)) {
          Utils.info('上传视频超过500MB,请重新录制')
          return
        }
        houseInfo[index].isUpdaLoaded = true
        this.setState({ houseMaterialInfo: houseInfo })
        if (res.tempFiles[0].duration > 25){
          Utils.info('上传视频超过25秒,请进行编辑')
          setTimeout(()=>{
            this.editVideo(res.tempFiles[0].tempFilePath, index, (res.tempFiles[0].width < res.tempFiles[0].height ? true : false))
          },1000)
          return 
        }else{
          if (Uploader.isSupport()) {
            this.uploadOne(res.tempFiles, 0, index, res.tempFiles[0].duration, (res.tempFiles[0].width < res.tempFiles[0].height ? true : false))
          } else {
            this.uploadLoadRecord(res.tempFiles[0])
          }
        }
      },
      fail: (err) => {
        // Utils.info('上传视频失败')
        houseMaterialInfo[index].mediaPath = ''
        houseInfo[index].isUpdaLoaded = false
        this.setState({ houseMaterialInfo: houseInfo })
      }
    })
  }
  editVideo = (videoPath, index, isPortraitVideo) =>{
    const { houseMaterialInfo } = this.state
    wx.openVideoEditor({
      filePath: videoPath,
      minDuration:15,
      maxDuration:25,
      success:(res)=> {
        if (Uploader.isSupport()) {
          this.uploadOne([res], 0, index, (res.duration / 1000), isPortraitVideo)
        } else {
          this.uploadLoadRecord(res.tempFilePath)
        }
        // 可以在这里处理编辑后的视频,例如上传到服务器
      },
      fail:(err)=> {
        let houseInfo = houseMaterialInfo
        houseInfo[index].isUpdaLoaded = false
        this.setState({ houseMaterialInfo: houseMaterialInfo })
        console.log('编辑视频失败',err);
        
      }
    });
  }


// 分片上传是一个用于上传视频文件的方法,isPortraitVideo 参数判断是否为竖屏视频
uploadOne(obj, n = 0, index, videoLength, isPortraitVideo) {
  // 获取当前组件的 state 中的 houseMaterialInfo 数据
  const { houseMaterialInfo } = this.state;
  
  // 根据环境选择上传和合并文件的 API 地址
  const uploadUrl = `${env === 'dev' || env === 'test' ? '上传地址' : '上传地址'}/xcx/v1/tool/chunk/upload-file`;
  const mergeUrl = `${env === 'dev' || env === 'test' ? '地址' : '地址'}/xcx/v1/tool/chunk/complete-upload`;

  // 如果没有文件要上传,直接退出
  if (typeof (obj[n]) === 'undefined') { return false }

  // 标记上传正在进行中
  this.isUploading = true;
  Utils.info('上传中...');  // 提示上传开始

  // 获取上传文件的路径
  const tempFilePath = obj[n].tempFilePath;
  
  // 获取当前时间并处理文件的扩展名和其它信息
  const d = new Date();
  const tmpArr = tempFilePath.split('.');
  const file = { fileName: '', ext: '', index: 0, now: 0, chunkSize: 5 * 1024 * 1024, dir: '' };
  file.now = parseInt(d.getTime() + '' + rndInt(1000, 9999), 10); // 生成唯一的文件名
  if (tmpArr.length > 1) { file.ext = tmpArr.pop().toLowerCase() } // 获取文件扩展名并转换为小写
  file.fileName = file.now + (file.ext !== '' ? '.' + file.ext : ''); // 拼接文件名
  file.index = Math.ceil(obj[n].size / file.chunkSize); // 计算文件的分片数
  file.dir = d.getFullYear() + '' + lt10(d.getMonth() + 1) + lt10(d.getDate()); // 生成文件上传目录

  // 引入签名模块,生成上传所需的签名
  const signature = require('@/signature/index.ts').default;
  const postBody = {
    url: uploadUrl,
    method: 'POST',
    header: {
      Authorization: ''
    }
  };

  // 为上传请求生成签名
  signature['api-b-livein.ke.com'](
    Object.assign(
      {
        headers: {}
      },
      postBody
    )
  );

  // 配置上传的选项
  const opt = {
    fileName: file.fileName,
    chunkSize: file.chunkSize,
    maxConcurrency: 5,  // 最多允许 5 个并发上传
    maxChunkRetries: 3, // 最大重试次数为 3
    chunkRetryInterval: 3000, // 每次重试的时间间隔为 3 秒
    totalSize: obj[n].size, // 文件总大小
    query: { fid: 1, dir: file.dir }, // 上传时的参数
    uploadUrl, // 分片上传 URL
    mergeUrl, // 合并分片 URL
    tempFilePath, // 临时文件路径
    timeout: 60000, // 超时时间设置为 60 秒
    header: {
      'Content-Type': 'multipart/form-data',  // 设置请求内容类型
      accept: 'application/json',  // 接受的响应格式
      'Livein-Access-Token': Utils.read('token'),  // 用户的访问令牌
      userId: Utils.read('daiKeUserId') || '', // 用户 ID
      Authorization: postBody.header.Authorization // 请求的 Authorization
    },
  };

  // 处理不同类型的文件,目前暂时没有根据类型做处理
  switch (obj[n].fileType) {
    case 'image':
      break;
    case 'video':
      break;
    default:
  }

  // 创建一个上传器实例
  const uploader = new Uploader(opt);

  // 处理上传重试事件
  uploader.on('retry', (res) => {});

  // 处理上传成功事件
  uploader.on('success', (res) => {
    // 如果上传成功,更新状态
    if (res.errno === 0 && res.data && res.data.path) {
      this.isUploading = false;  // 标记上传完成
      houseMaterialInfo[index].mediaPath = res.data.path;  // 存储文件路径
      houseMaterialInfo[index].videoUrl = tempFilePath;  // 存储视频的本地路径
      houseMaterialInfo[index].isUpdaLoaded = false;  // 更新状态
      // 判断视频长度和是否竖屏,如果不符合要求,提示上传限制
      if (parseInt(videoLength) < 15 || parseInt(videoLength) > 25 || !isPortraitVideo) {
        houseMaterialInfo[index].suggestText = '请上传 15s~25s的竖版视频';
      }
      this.setState({ houseMaterialInfo });  // 更新组件的状态
    } else {
      this.isUploading = false;  // 上传失败时,标记上传状态
      houseMaterialInfo[index].isUpdaLoaded = false;  // 标记为上传失败
      this.setState({ isUploading: false, houseMaterialInfo });
      Utils.info(res.error || '上传失败');  // 显示错误信息
    }
  });

  // 处理上传失败事件
  uploader.on('fail', (res) => {
    this.isUploading = false;
    houseMaterialInfo[index].isUpdaLoaded = false;
    this.setState({ isUploading: false, houseMaterialInfo });
    Utils.info(res.error || '上传失败');  // 显示上传失败的错误信息
  });

  // 处理上传进度事件
  uploader.on('progress', (res) => {
    const tmp = {
      eq: n,
      size: obj[n].size / 1024, // 文件大小(KB)
      progress: res.progress,  // 上传进度
      uploadedSize: parseInt(`${res.uploadedSize / 1024}`), // 已上传的大小(KB)
      averageSpeed: parseInt(`${res.averageSpeed / 1024}`),  // 平均上传速度(KB/s)
      timeRemaining: res.timeRemaining / 1000  // 剩余上传时间(秒)
    };
    this.setState({ upload: tmp });  // 更新上传进度
  });

  // 开始上传文件
  uploader.upload();
  this.uploader = uploader;  // 保存上传实例
}

// 上传资源文件的方法
uploadLoadRecord = (paramRes) => {
  // 如果当前已经有文件在上传,禁止重复上传
  if (this.isUploading) return;

  // 设置上传 URL
  const url = `${env === 'dev' || env === 'test' ? 'http://test-i.app-api-b.ttb.test.ke.com' : 'https://api-b-livein.ke.com'}/xcx/v1/tool/upload-resource`;
  
  // 标记上传正在进行中
  this.isUploading = true;
  Utils.info('上传中...');
  this.setState({ isUploading: true });

  // 为上传请求生成签名
  const signature = require('@/signature/index.ts').default;
  const postBody = {
    url,
    method: 'POST',
    header: {
      Authorization: ''
    }
  };
  signature['api-b-livein.ke.com'](
    Object.assign(
      {
        headers: {}
      },
      postBody
    )
  );

  // 使用 Ditto 库上传文件
  Ditto.uploadFile({
    url,
    filePath: paramRes.tempFilePath,  // 文件的路径
    name: 'resource',  // 文件表单字段名
    formData: {},
    header: {
      'Content-Type': 'multipart/form-data',
      accept: 'application/json',
      'Livein-Access-Token': Utils.read('token'),  // 用户令牌
      userId: Utils.read('daiKeUserId') || '',  // 用户 ID
      Authorization: postBody.header.Authorization  // 请求的 Authorization
    },
    success: res => {
      // 解析返回的数据,上传成功时更新状态
      const respon = JSON.parse(res.data);
      if (respon.errno === 0 && respon.data && respon.data.path) {
        this.setState({ isUploading: false, upLoadingIndex: -1 });
        this.isUploading = false;
        this.setState({
          videoPath: respon.data.path,  // 上传成功后返回的视频路径
          videoSrc: paramRes.tempFilePath  // 视频源路径
        });
      } else {
        this.isUploading = false;
        this.setState({ isUploading: false, upLoadingIndex: -1 });
        Utils.info(respon.error || '上传失败');  // 显示错误信息
      }
    },
    fail: err => {
      // 上传失败时的处理
      this.isUploading = false;
      this.setState({ isUploading: false, upLoadingIndex: -1 });
      Utils.info(err || '上传失败');  // 显示上传失败的错误信息
    }
  });
};

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值