taro小程序如何实现大文件(视频、图片)后台下载功能?

一、需求背景

1、需要实现小程序下载最大500M视频

2、同时需支持图片下载

3、退到其他页面再次回到当前页面时,下载进度也需要展示

二、实现步骤

1、在app.ts文件定义一个全局变量globalDownLoadData

2、写一个独立的下载hooks,代码如下(hooks/useDownLoad.ts文件)

bash 复制代码
import Taro, { useDidShow } from '@tarojs/taro';
import { useState, useCallback, useEffect, useRef } from 'react';
import { tips } from '@/modules/utils/log';
import { GET_ENV } from '@/modules/core/env';

// 下载选项接口
interface DownloadOptions {
  /** 下载文件的URL */
  url: string;
  // 下载的是图片还是视频,默认是视频
  isImg?: boolean;
  // 下载成功后的回调
  successFn?: () => void;
}

// 请注意_taskId格式应该为:`material_${routerParams.id}`
// material为页面标志,请注意唯一性,避免不同页面的id重复
export const useDownLoad = _taskId => {
  const taskId = `${GET_ENV()}_${_taskId}`;
  const globalDownLoadData = useRef(Taro.getApp().globalDownLoadData);

  const [progress, setProgress] = useState(0);

  useDidShow(() => {
    // 恢复目标页面下载进度
    setProgress(globalDownLoadData.current[taskId]?.progress || 0);
  });
  useEffect(() => {
    globalDownLoadData.current[taskId] = {
      progress,
      downloadTask: globalDownLoadData.current[taskId]?.downloadTask
    };
  }, [progress]);
  // 赋值数据给全局
  useEffect(() => {
    Taro.getApp().globalDownLoadData = globalDownLoadData.current;
  }, [globalDownLoadData]);
  useEffect(() => {
    // 再次进入页面时,将监听加上
    addProgressUpdate();
  }, []);

  /**
   * 执行文件下载
   * @param options 下载选项
   */
  const downloadFn = useCallback(async (options: DownloadOptions) => {
    try {
      setProgress(0);

      // 创建下载任务
      globalDownLoadData.current[taskId].downloadTask = Taro.downloadFile({
        url: options.url,
        success: async res => {
          if (res.statusCode === 200) {
            // 下载成功,保存到相册
            Taro.getSetting({
              success(settingRes) {
                // 是否相册授权,已授权直接保存图片
                if (settingRes.authSetting['scope.writePhotosAlbum']) {
                  const Api = options.isImg ? 'saveImageToPhotosAlbum' : 'saveVideoToPhotosAlbum';
                  Taro[Api]({
                    filePath: res.tempFilePath,
                    success() {
                      tips('下载完成');
                      options.successFn?.();
                      // 下载完成后清除进度
                      setProgress(0);
                    },
                    fail(err) {
                      console.log('saveImageToPhotosAlbum err', err);
                      setProgress(0);
                    }
                  });
                  // 未授权,则先授权
                } else {
                  Taro.authorize({
                    scope: 'scope.writePhotosAlbum',
                    fail() {
                      tips('下载失败,请先点击右上角获取授权');
                      setProgress(0);
                    }
                  });
                }
              },
              fail(err) {
                setProgress(0);
                tips('下载失败,请稍后再试');
                console.log('getSetting err', err);
              }
            });
          } else {
            // 下载失败
            setProgress(0);
            tips('下载失败,请稍后再试');
            console.log('downloadFile下载出错了:', res);
          }
        },
        fail: error => {
          // 下载出错
          setProgress(0);
          globalDownLoadData.current[taskId] = {
            progress: 0,
            downloadTask: null
          };
          console.log('下载出错了:', error);
          Taro.showModal({
            title: '下载异常',
            content: '下载异常或文件大小超过小程序限制,请通过浏览器下载!',
            confirmColor: '#3f57ff',
            success: modalRes => {
              if (modalRes.confirm) {
                Taro.setClipboardData({
                  data: options.url,
                  success() {
                    tips('资源链接已复制');
                  }
                });
              }
            }
          });
        }
      });

      addProgressUpdate();
    } catch (error) {
      // 捕获其他异常
      tips('下载失败,请稍后再试');
      console.log('downloadFn下载失败======>', error);
      setProgress(0);
    }
  }, []);
  // 监听下载进度变化
  const addProgressUpdate = () => {
    const downloadTask = globalDownLoadData.current[taskId]?.downloadTask;
    if (!downloadTask) {
      setProgress(0);
      return;
    }
    downloadTask.onProgressUpdate(res => {
      if (res.progress >= 100) {
        // 下载完成时,延迟2秒后清除进度
        setTimeout(() => {
          setProgress(0);
          downloadTask.abort();
          delete globalDownLoadData.current[taskId];
        }, 2000);
      } else {
        setProgress(res.progress);
      }
    });
  };

  return {
    downloadFn,
    progress
  };
};

3、页面使用

bash 复制代码
import { useDownLoad } from '@/subPages/hooks/useDownLoad';

const { downloadFn, progress } = useDownLoad(`material_${routerParams.id}`);

const onDownload = () => {
    if (!curUrl) {
      tips('下载资源不存在');
      return;
    }
    Taro.showModal({
      title: '提示',
      confirmColor: '#3f57ff',
      content: '确定要下载该素材吗?',
      success: async res => {
        if (res.confirm) {
          downloadFn({
            url: curUrl,
            isImg: false
          });
        }
      }
    });
  };

四、参考文档:

https://developers.weixin.qq.com/miniprogram/dev/api/network/download/wx.downloadFile.html

https://developers.weixin.qq.com/miniprogram/dev/api/media/image/wx.saveImageToPhotosAlbum.html

https://developers.weixin.qq.com/miniprogram/dev/api/media/video/wx.saveVideoToPhotosAlbum.html

相关推荐
2301_7903559731 分钟前
【技术拆解】短视频配音自动化流程:从文案预处理到 SRT 字幕的 9 个环节
自然语言处理·音视频
wx1qq1com4 小时前
一桩带几台车:共享租赁桩位配比、取电与结算闭环设计
物联网·微信小程序·小程序
大飞哥软件自习室5 小时前
视频批量截图并自动拼图是怎么做的:从四步向导、三种截帧模式到等距抽样与日志兜底的实现拆解,附 FFmpeg 调用与线程模型说明
ffmpeg·音视频·批量截图
2401_879692516 小时前
微信小程序照相与摄像功能实现——chooseImage 与 chooseVideo 详解
微信小程序·小程序·notepad++
律宏阔1 天前
微信小程序 + Taro + TDesign 去掉 [&&&],让普通 Tailwind 类接管局部样式
前端·微信小程序·taro
律宏阔1 天前
微信小程序 + Taro + 多语言实现与国际化检查实录
前端·微信小程序·taro
Black蜡笔小新1 天前
消防控制室/配电房/中控室...视频汇聚平台EasyCVR岗位AI智能监测方案守住关键岗位
大数据·音视频·easycvr
FlightYe2 天前
音视频修炼之容器与协议(四):RTSP详解
android·linux·ffmpeg·音视频·dash
李纲明2 天前
微信小程序 getSystemInfo 提示已废弃、屏幕高度算错胶囊还对不齐?getWindowInfo 和 getDeviceInfo 怎么接才稳
javascript·微信小程序·小程序·小程序开发·devdiy
乐橙开放平台2 天前
海康和大华摄像头能统一管理吗?可以通过 GB28181 或视频融合平台接入
网络·后端·物联网·音视频