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

自定义Taro上传图片hooks(useUploadImg)

有两个方法需要提前引入 FileUtil(上传文件的方法)、to(对请求接口返回做了二次处理,数据和错误提示等)

//FileUtil
export namespace FileUtil {
  const env = {
    timeout: 10000,
    uploadImageUrl: "阿里云的地址",
  };

  const genPolicy = () => {
    let date = new Date();
    date.setHours(date.getHours() + env.timeout);
    let srcT = date.toISOString();
    const policyText = {
      expiration: srcT,
      conditions: [
        ["content-length-range", 0, 1 * 1024 * 1024 * 1024], // 设置上传文件的大小限制1G
      ],
    };
    var rawStr = JSON.stringify(policyText);
    var wordArray = Utf8.parse(rawStr);
    var policyBase64 = Base64.stringify(wordArray);
    return policyBase64;
  };

  const genSignature = (policyBase64, accessKey) => {
    const byte = HmacSHA1(policyBase64, accessKey);
    const signature = Base64.stringify(byte);
    return signature;
  };

  export const upload = async (
    fileInfo
  ): Promise<{ url: string; errMsg: string }> => {
    const { path } = fileInfo;
    return new Promise(async (resolve) => {
      const res = await httpRequest({
        url: "图片上传的接口",
        method: "POST",
      });
      if (res?.code === 200 && res?.data) {
        const {
          Credentials: { AccessKeyId, AccessKeySecret, SecurityToken },
        } = res.data;
        const aliyunFileKey =
          "mini_" + new Date().getTime() + path.split("tmp/")[1]; //文件命名

        const policyBase64 = genPolicy();
        const signature = genSignature(policyBase64, AccessKeySecret);

        //小程序直传oss
        Taro.uploadFile({
          url: env.uploadImageUrl,
          filePath: path,
          name: "file",
          header: {
            "Content-Type": "multipart/form-data",
          },
          formData: {
            key: aliyunFileKey,
            policy: policyBase64,
            OSSAccessKeyId: AccessKeyId,
            signature: signature,
            "x-oss-security-token": SecurityToken, //使用STS签名时必传。
            success_action_status: "200",
          },
          success: function (resp) {
            if (resp?.statusCode === 200) {
              resolve({
                url: env.uploadImageUrl + aliyunFileKey,
                errMsg: "ok",
              });
            } else {
              resolve({ url: "", errMsg: resp?.errMsg });
            }
          },
          fail: function (err: any) {
            resolve({ url: "", errMsg: err });
          },
        });
      } else {
        resolve({ url: "", errMsg: res?.msg });
      }
    });
  };
}
//to
export async function to<T>(promise: Promise<T>): Promise<[Error | null, T]> {
  if (!promise || !Promise.prototype.isPrototypeOf(promise)) {
    // @ts-ignore
    return await new Promise((resolve, reject) => {
      reject(new Error("request promises as ths param"));
    }).catch((error) => {
      return [error, null];
    });
  }

  // @ts-ignore
  return await promise
    .then(function () {
      // @ts-ignore
      return [null, ...arguments];
    })
    .catch((error) => {
      return [error, null];
    });
}
import { useState } from "react";
import { FileUtil, to } from "@/utils";
import Taro from "@tarojs/taro";
import { useLoading } from "taro-hooks";

interface UseUploadImgProps {
  maxLength?: number;
  initList?: string[];
}
export const useUploadImg = ({
  maxLength = 9,
  initList = [],
}: UseUploadImgProps) => {
  const [fileList, setFileList] = useState<string[]>([...initList || []]);
  const [showLoading, hideLoading] = useLoading({
    title: "上传中...",
    mask: true,
  });

  const handleUpload: (
    path: any
  ) => Promise<{ url: string; errMsg: string }> = async (path) => {
    return FileUtil.upload({ path });
  };

  const handleSendImage = async () => {
    // 选择图片
    const chooseImgResp = await to(
      Taro.chooseImage({
        count: maxLength - fileList?.length,
        sizeType: ["original"],
        sourceType: ["album", "camera"],
      })
    );

    if (chooseImgResp[0]) {
      return;
    }

    if (chooseImgResp[1].errMsg !== "chooseImage:ok") {
      return;
    }

    const filesLen = chooseImgResp[1].tempFilePaths?.length;
    let asyncArr: Promise<{ url: string; errMsg: string }>[] = [];
    for (let i = 0; i < filesLen; i++) {
      asyncArr.push(handleUpload(chooseImgResp[1].tempFilePaths[i]));
      // 获取图片信息
    }
    showLoading().then();
    Promise.all(asyncArr)
      .then((res) => {
        const upLoadList = res.filter(obj => obj.url !== '').map(item=>item.url);
        setFileList((val) => [...val, ...upLoadList]);
      })
      .catch(() => {
        Taro.showToast({ title: "上传失败,请重试", icon: "none" });
      })
      .finally(() => {
        hideLoading().then();
      });
  };

  return {
    handleSendImage,
    fileList,
    setFileList,
  };
};

在页面中使用

import { useUploadImg } from "定义hook的文件地址";
import Taro, { showToast } from "@tarojs/taro";
import { Image, View } from "@tarojs/components";

export const UpLoadImg = () => {
 const { handleSendImage, fileList, setFileList } = useUploadImg({
    maxLength,
  }); // 这里就是useUploadImg 输出的方法和上传文件的list
  <View>
  {fileList.map((item, index) => (
    <View key={item}>
      <Image
        src={item}
        onClick={() => {
          if (fileList) {
            Taro.previewImage({
              urls: fileList,
              current: item,
            });
          }
        }}
      />
      <Image
        src={iconDelete}
        className={styles.imgDelete}
        onClick={() => {
          fileList.splice(index, 1);
          setFileList(() => [...fileList]);
        }}
      />
    </View>
  ))}
  {fileList.length < maxLength && (
    <View onClick={() => handleSendImage()}>
      <Image />
    </View>
  )}
</View>
})



在这里插入图片描述
在这里插入图片描述

相关文章:

  • 让生活更智能,P1600边缘智能网关带你进入智能家居新时代
  • C#学习笔记 - C#基础知识 - C#从入门到放弃 - C# 结构、类与属性
  • 【起草】【第六章】ChatGPT 在软件测试的应用场景
  • 物联网主机E6000:引领智能安防新时代
  • display:grid
  • 【Java之数据结构与算法】
  • .NET面试题(二)
  • 在 Go 语言中使用 regexp 包处理正则表达式
  • node实现简单的数据爬虫
  • Python轴承故障诊断 (八)基于EMD-CNN-GRU并行模型的故障分类
  • 【C语言】动态内存管理基础知识——动态通讯录,如何实现通讯录容量的动态化
  • 【JavaWeb学习笔记】14 - 三大组件其二 Listener Filter
  • 【Docker】基于华为 openEuler 应用 Docker 镜像体积压缩
  • Gazebo GUI模型编辑器
  • C语言之初识C语言
  • 在Portainer创建Nginx容器并部署Web静态站点实现公网访问
  • 【C语言】6-5 判断回文字符串 分数 20
  • Flink系列之:Savepoints
  • 第二章、动态规划算法(2.5.3-2.5.4.3)------公共序列问题(下)
  • 二分查找法详解(6种变形)
  • 国博馆刊|北朝至唐初夏州酋豪李氏家族的发展与身份记忆
  • 美联储主席:美联储工作方式不会受特朗普影响,从未寻求与总统会面
  • 百济首次实现季度营业利润扭亏,泽布替尼销售额近57亿元
  • 上海市委常委会扩大会议传达学习习近平总书记考察上海重要讲话和在部分省区市“十五五”时期经济社会发展座谈会上的重要讲话精神
  • 安顺市原副市长、市公安局原局长顾长华任贵州省民委副主任
  • “高校领域突出问题系统整治”已启动,聚焦招生、基建、师德等重点