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

news2025/2/6 9:58:53

有两个方法需要提前引入 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>
})



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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1327962.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

搭载紫光展锐芯的移远通信RedCap模组顺利通过中国联通OPENLAB实验室认证

近日&#xff0c;移远通信联合紫光展锐在中国联通5G物联网OPENLAB开放实验室&#xff0c;完成了RedCap模组RG207U-CN端到端测试验收&#xff0c;并获颁认证证书。移远通信RG207U-CN成为业内率先通过联通OPENLAB认证的紫光展锐RedCap芯片平台的模组。 本次测试基于联通OPENLAB实…

网络技术基础与计算思维实验教程_4.1_PSTN和以太网互连实验

实验内容 实验目的 实验原理 关键命令说明 实验步骤 构建以太网 工作区中放置路由器 交换机 PC机 直通线互连PC0和交换机 交换机和路由器 构建PSTN 放置PSTN 放置PC 为路由器安装modem 打开电源 再为终端安装modem 单击路由器选择图形配置 这个IP地址将成为PC0的默认网关地…

跆拳道加盟培训机构管理系统源码开发方案

一、项目背景与目标 &#xff08;一&#xff09;项目背景 跆拳道加盟培训机构管理系统源码开发方案旨在为跆拳道培训机构提供一个全面、高效的管理平台&#xff0c;帮助机构实现学员管理、课程安排、财务管理等方面的自动化和信息化。 &#xff08;二&#xff09;项目可行性…

debian10安装配置vim+gtags

sudo apt install global gtags --version gtags //生成gtag gtags-cscope //查看gtags gtags与leaderf配合使用 参考: 【VIM】【LeaderF】【Gtags】打造全定制化的IDE开发环境&#xff01; - 知乎

vue:ref的作用和实例

定义&#xff1a;用来获取元素或子组件注册或者引用信息&#xff0c;父组件通过$ref获取到相应的DOM对象和子组件 1、vue中ref的作用 获取页面的DOM元素获取子组件的对象&#xff08;也是一种通信方式&#xff09; 2、实例 1、获取DOM&#xff0c;首先创建一个父页面index然…

IDEA中Git的常用使用方式

IDEA中Git的常用使用方式 1.初次拉取远程仓库项目代码到本地2.初次提交本地项目代码到远程仓库新分支方式一&#xff1a;提交时把.git目录删除掉&#xff0c;不保留以往修改记录方式二&#xff1a;提交时不删除.git目录&#xff0c;保留以往修改记录 3.日常拉取、提交、推送代码…

虚幻学习笔记20—C++中用户输入控制

一、前言 用户输入主要有鼠标和键盘以及其他的遥感外接设备等&#xff0c;在虚幻中经常会用到这些输入设备的值&#xff0c;比如通过鼠标控制摄像头的方向、键盘控制人物移动等。本文主要讲解简单的输入绑定和虚幻5新增的”增强输入控制“两种方法。 二、实现 2.1、原始的输入…

机器学习--线性回归

目录 监督学习算法 线性回归 损失函数 梯度下降 目标函数 更新参数 批量梯度下降 随机梯度下降 小批量梯度下降法 数据预处理 特征标准化 正弦函数特征 多项式特征的函数 数据预处理步骤 线性回归代码实现 初始化步骤 实现梯度下降优化模块 损失与预测模块 …

FastAPI实现文件上传下载

FastAPI实现文件上传下载 1.后端FastAPI2.后端html3.效果 最近的项目需求&#xff0c;是前端vue&#xff0c;后端fastAPI&#xff0c;然后涉及到图像的消息发送&#xff0c;所以需要用fast写文件上传下载的接口&#xff0c;这里简单记录一下。 1.后端FastAPI import os.path i…

【藏经阁一起读】(80)__《2023龙蜥社区白皮书》

【藏经阁一起读】&#xff08;80&#xff09;__《2023龙蜥社区白皮书》 2023龙蜥社区白皮书 作者&#xff1a; 小龙 发布时间&#xff1a;2023-11-15 章节数&#xff1a;79 内容简介&#xff1a; 从解决CentOS停服的问题出发为广大用户的业务连续性提供了坚定的保障&#xf…

R语言【cli】——通过cli_abort用 cli 格式的内容显示错误、警告或信息,内部调用cli_bullets和inline-makeup

cli_abort(message,...,call .envir,.envir parent.frame(),.frame .envir ) 先从那些不需要下大力气理解的参数入手&#xff1a; 参数【.envir】&#xff1a;进行万能表达式编译的环境。 参数【.frame】&#xff1a;抛出上下文。默认用于参数【.trace_bottom】&#xff…

Python---socket 的介绍

1. 问题思考 到目前为止我们学习了 ip 地址和端口号还有 tcp 传输协议&#xff0c;为了保证数据的完整性和可靠性我们使用 tcp 传输协议进行数据的传输&#xff0c;为了能够找到对应设备我们需要使用 ip 地址&#xff0c;为了区别某个端口的应用程序接收数据我们需要使用端口号…

MySQL数据库8.0+版本部署安装

1、安装前准备 1.1、安装文件上传 以mysql-8.0.32版本为例&#xff0c;将 mysql-8.0.32-linux-glibc2.12-x86_64.tar.xz 、my.cnf上传至/opt/software目录。 安装文件百度网盘下载地址&#xff1a; mysql-8.0.32&#xff1a;https://pan.baidu.com/s/1gtPYEa2aT0V2-1Q3-KKxl…

【SpringMVC】REST(Representation State Transfer)ful开发

REST全称Representation State Transfer&#xff0c;表现形式状态转换 文章目录 1. 为什么提出了REST&#xff1f;2. RESTful入门案例案例代码修改请求方式修改成RESTful风格&#xff0c;并以POST方式提交 RESTful格式下传参RESTful入门案例总结RequestBody&#xff0c;Reques…

【高效开发工具系列】eclipse部署web项目

&#x1f49d;&#x1f49d;&#x1f49d;欢迎来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐:kwan 的首页,持续学…

Go 随机密码

一.Go实现随机密码 随机密码 package mainimport ("fmt""math/rand""os""strconv""time" )func RandomPassword(num int) {length : numif len(os.Args) > 1 {arg : os.Args[1]i, err : strconv.ParseInt(arg, 10, 6…

LeetCode做题总结 1. 两数之和

1. 两数之和 暴力法哈希法重新分析Java语法 暴力法 2023.09.20 刚开始用暴力法破解&#xff08;C&#xff09; class Solution { public:vector<int> twoSum(vector<int>& nums, int target) {vector<int> a;for(int i0; i<nums.size()-1; i) {for(…

flink watermark 实例分析

WATERMARK 定义了表的事件时间属性&#xff0c;其形式为: WATERMARK FOR rowtime_column_name AS watermark_strategy_expression rowtime_column_name 把一个现有的列定义为一个为表标记事件时间的属性。该列的类型必须为 TIMESTAMP(3)/TIMESTAMP_LTZ(3)&#xff0c;且是 sche…

pdf 在线编辑

https://smallpdf.com/edit-pdf#rapp 参考 https://zh.wikihow.com/%E5%B0%86%E5%9B%BE%E5%83%8F%E6%8F%92%E5%85%A5PDF

网络基础篇【网线的制作,OSI七层模型,集线器和交换机的介绍,路由器的介绍与设置】

目录 一、网线制作 1.1 工具介绍 1.1.1网线 1.1.2 网线钳 1.1.3 水晶头 1.1.4 网线测试仪 二、OSI七层模型 2.1 简介 2.2 OSI模型层次介绍 2.2.1 结构图 2.2.2 数据传输过程 2.3 相关网站 二、集线器 2.1 介绍 2.2 适用场景 三、交换机 3.1 介绍 3.2 适用场景…