完美实现微信小程序下载视频功能

5,471 阅读3分钟

这是我参与8月更文挑战的第24天,活动详情查看:8月更文挑战

简单介绍

基于 uni-app 开发的微信小程序下载视频功能

下载视频 简单写法

uni.downloadFile({
    url: 'http://wxsnsdy.tc.qq.com/105/20210/snsdyvideodownload?filekey=30280201010421301f0201690402534804102ca905ce620b1241b726bc41dcff44e00204012882540400&bizid=1023&hy=SH&fileparam=302c020101042530230204136ffd93020457e3c4ff02024ef202031e8d7f02030f42400204045a320a0201000400',
    success: (res) => {
      uni.saveVideoToPhotosAlbum({
        filePath: res.tempFilePath,
        success:(res) => {
          this.createDownRecord(item.url, 2)
           uni.showToast({
            title: '下载成功',
            icon: 'success',
          })
        }
      })
    }
})

这种写法有点问题,

第一 如果视频文件过大,或者网络状态不佳, 没有提示,不知道当前下载进度,不友好

第二 当响应头中 content-type 为以下 值时

Content-Type: application/octet-stream

ios 端下载视频会有问题(自测小程序模拟器和安卓手机下载没问题) 会提示错误 saveVideoToPhotosAlbum:fail invalid file type

原因,苹果手机端小程序 不支持临时文件路径 缓存,所以需要在 uni.downloadFile中需要配置filePath(指定文件下载下来保存的本地址)

先解决第一个问题 优化提示信息

优化提示信息 提示下载进度百分比

用到了 小程序的 Api DownloadTask.onProgressUpdate

uni-app 也延用了 这个api

const task = uni.downloadFile({
    url: videoUrl,
    success: (res) => {
      uni.saveVideoToPhotosAlbum({
        filePath: res.tempFilePath,
        success:(res) => {
          this.createDownRecord(item.url, 2)
           uni.showToast({
            title: '下载成功',
            icon: 'success',
          })
        }
      })
    }
})
task.onProgressUpdate(this.onProgress)

// 提示下载进度
onProgress(res){
  uni.showToast({
    icon:'loading',
    mask:true,
    title: res.progress + "%"
  })
}

第二个问题 兼容 苹果端小程序视频下载

方案一

简单点话就是 前端不用改,后端配置 响应头 为以下值 就完美解决了

    Content-Type: video/mp4

方案二

还有一种是 前端是来处理 解决思路 既然 不支持 临时缓存文件 地址,那就直接保存到用户目录路径 (本地路径),待保存完毕后,再删除掉这个文件,这样相当于手动实现了 临时缓存文件

1.需要自定义文件名称

let fileName = new Date().valueOf();

2.需要访问 文件系统中的用户目录路径 (本地路径)

USER_DATA_PATH(来自wx.env)

3.需要用到小程序的 获取全局唯一的文件管理器的api

getFileSystemManager

4.还有删除文件的api

FileSystemManager.unlink

具体实现

// 下载视频
downloadVideo(url){
  // 自定义 文件名称
  let fileName = new Date().valueOf();
  const task = uni.downloadFile({
    url: url,
    filePath: wx.env.USER_DATA_PATH + '/' + fileName + '.mp4',
    //  拼接本地文件路径
    success: (res) => {
      let filePath = res.filePath
      uni.saveVideoToPhotosAlbum({
        filePath,
        success:(res) => {
          uni.showToast({
            title: '下载成功',
            icon: 'success',
          })
          let fileMgr = wx.getFileSystemManager();
          // 删除本地文件
          fileMgr.unlink({
            filePath: wx.env.USER_DATA_PATH + '/' + fileName + '.mp4',
            success: function(r) {
              console.log('unlink-getFileSystemManager')
              console.log(r)
            },
          })
        },
        complete(res) {
          console.log('saveVideoToPhotosAlbum-complete')
          console.log(res)
        }
      })
    },
    complete(res) {
      console.log('downloadFiledownloadFiledownloadFiledownloadFiledownloadFile')
      console.log(res)
      uni.hideLoading()
    }
  })
  task.onProgressUpdate(this.onProgress)
},

完整代码

<template>
    <view>
        <video class="videos" :src="url" @error="ErrorCallback" controls> </video>
        </view>
        <view class="btn" @click="downloadVideo(url)">下载视频</view>
    </view>
<template>
export default {
  name:'greetingStore',
  components:{
    action,
    firstPciture,
    poster,
    videos,
    greetMsg
  },
  data(){
    return {
      url:  'http://wxsnsdy.tc.qq.com/105/20210/snsdyvideodownload?filekey=30280201010421301f0201690402534804102ca905ce620b1241b726bc41dcff44e00204012882540400&bizid=1023&hy=SH&fileparam=302c020101042530230204136ffd93020457e3c4ff02024ef202031e8d7f02030f42400204045a320a0201000400'
    }
  },
  methods:{
    // 下载视频
    downloadVideo(url){
      // 自定义 文件名称
      let fileName = new Date().valueOf();
      const task = uni.downloadFile({
        url: url,
        filePath: wx.env.USER_DATA_PATH + '/' + fileName + '.mp4', //  拼接本地文件路径
        success: (res) => {
          let filePath = res.filePath
          uni.saveVideoToPhotosAlbum({
            filePath,
            success:(res) => {
              uni.showToast({
                title: '下载成功',
                icon: 'success',
              })
              let fileMgr = wx.getFileSystemManager();
              // 删除本地文件
              fileMgr.unlink({
                filePath: wx.env.USER_DATA_PATH + '/' + fileName + '.mp4',
                success: function(r) {
                  console.log('unlink-getFileSystemManager')
                  console.log(r)
                },
              })
            },
            complete(res) {
              console.log('saveVideoToPhotosAlbum-complete')
              console.log(res)
            }
          })
        },
        complete(res) {
          console.log('downloadFiledownloadFiledownloadFiledownloadFiledownloadFile')
          console.log(res)
          uni.hideLoading()
        }
      })
      task.onProgressUpdate(this.onProgress)
    },
    // 提示下载进度
    onProgress(res){
      uni.showToast({
        icon:'loading',
        mask:true,
        title: res.progress + "%"
      })
    },
  }
}

待优化

  1. 可在封装成一个公共方法,支持回调事件,也简单 用 Promise 实现就可以了
  2. 完善提示下载进度,可以优化下 样式,考虑用 u-viwe框架中的 进度条组件

以上就是本篇的全部内容了,非常感谢帅哥美女们能看到这里,如果这个文章写得还不错或者对你有一点点帮助,求点赞,求关注,求分享,当然有任何问题可以在评论讨论,我都会积极回答的,再次感谢😁