uniapp h5端临时路径转file对象上传

文章目录

  • 问题说明
  • 使用说明
    • 1.使用场景
    • 2. 文件需要压缩
    • 3. 使用技术
    • 4. 代码如下
    • 5. utils/index.js 代码
  • 3. 总结说明

问题说明

  1. 只针对uniapp开发H5网页,使用uniapp api获取到的临时路径不能满足使用场景,其他平台未进行测试

使用说明

1.使用场景

使用uview-ui的u-upload组件上传图片

2. 文件需要压缩

我的业务场景是上传图片之后,需要使用ocr识别,文件太大的话,识别比较缓慢,所以需要进行压缩

3. 使用技术

// npm install compressorjs
import Compressor from 'compressorjs';

4. 代码如下

这是在u-upload组件的基础上进行封装的ImageUpload组件, 先获取到临时路径,通过fetch请求获取到blob对象,然后再进行转file处理,相应的处理函数是tempFilePathToFile,compressFile

<template><view class="upload-container"><u-upload :previewImage="true" :max-count="maxCount" :auto-upload="false" @afterRead="handleAfterRead"@beforeRead="handleBeforeRead" :useBeforeRead="true" @delete="handleDelete" :multiple="multiple":accept="accept" :fileList="fileList"><slot name="file"></slot></u-upload></view>
</template><script>
import { getToken, tempFilePathToFile, compressFile } from "@/utils";
import { uploadFile } from "@/utils/api";export default {data() {return {fileList: [// {//     url: "/dev-api/profile/upload/2024/10/30/公司logo_20241030231031A009.jpg",// },],};},props: {value: [String, Object, Array],maxCount: {type: Number,default: 1,},// 文件大小限制 MfileSize: {type: Number,default: 20,},fileType: {type: Array,default: () => ["jpg", "png", "jpeg"],},accept: {type: String,default: "image",},multiple: {type: Boolean,default: false,},//  是否压缩的阈值 单位Mthreshold: {type: Number,default: 1,},},watch: {value: {handler(val) {if (val) {// 首先将值转为数组const list = Array.isArray(val)? val: this.value.split(",");// 然后将数组转为对象数组this.fileList = list.map((item) => {if (typeof item === "string") {let baseURL = this.globalVar.request.baseURL;if (item.indexOf(baseURL) === -1) {item = {name: baseURL + item,url: baseURL + item,};} else {item = { name: item, url: item };}}return item;});} else {this.fileList = [];return [];}},deep: true,immediate: true,},},methods: {// uploadFilePromise(url) {//     return new Promise((resolve, reject) => {//         uni.uploadFile({//             url: `${this.globalVar.request.baseURL}/common/upload`, // 仅为示例,非真实的接口地址//             filePath: url,//             name: "file",//             header: {//                 Authorization: "Bearer " + getToken(),//             },//             success: (res) => {//                 setTimeout(() => {//                     resolve(JSON.parse(res.data));//                 }, 1000);//             },//         });//     });// },uploadFilePromise(file) {return new Promise(async (resolve, reject) => {try {let formData = new FormData();formData.append("file", file, file.name);fetch(`${this.globalVar.request.baseURL}/common/upload`, {method: "POST",headers: {Authorization: "Bearer " + getToken(),},body: formData,}).then((res) => res.json()).then((res) => {resolve(res);});} catch (error) {console.log(error);resolve(null);}});},handleBeforeRead(e) {let files = typeof e.file === "object" ? [e.file] : e.file;let isLimitSize = files.some((file) => file.size > this.fileSize * 1024 * 1024);if (isLimitSize) {this.$u.toast(`文件大小不能超过${this.fileSize}MB`);return false;}let isLimitType = files.some((file) => !this.fileType.includes(file.name.split(".").pop()));if (isLimitType) {this.$u.toast(`仅支持${this.fileType.join(",")}格式`);return false;}return true;},async handleAfterRead(e) {let files = typeof e.file === "object" ? [e.file] : e.file;files.map((item) => {this.fileList.push({...item,status: "uploading",message: "上传中",});});let start = 0;for (let i = 0; i < files.length; i++) {let item = files[i];let file = await tempFilePathToFile({tempFilePath: item.url,fileName: item.name,});// 判断是否需要压缩if (file.size > this.threshold * 1024 * 1024) {file = await compressFile(file, { quality: 0.2 });}let res = await this.uploadFilePromise(file);if (res.code == 200) {this.fileList.splice(start,1,Object.assign(item, {status: "success",message: "",url: this.globalVar.request.baseURL + res.fileName,}));} else {this.fileList.splice(start,1,Object.assign(item, {status: "error",message: "上传失败",}));}start++;}this.$emit("input", this.listToString(this.fileList));let list = this.fileList.map((item) => {item.url = item.url.replace(this.globalVar.request.baseURL, "");return item;});this.$emit("change", list);},handleDelete(e) {this[`fileList`].splice(e.index, 1);this.$emit("input", this.listToString(this.fileList));// this.$emit("change", this.fileList);},// 对象转成指定字符串分隔listToString(list, separator) {let strs = "";separator = separator || ",";for (let i in list) {if (list[i].url) {strs +=list[i].url.replace(this.globalVar.request.baseURL,"") + separator;}}return strs != "" ? strs.substr(0, strs.length - 1) : "";},},
};
</script><style scoped>
.upload-container {padding: 20px;
}.upload-btn {display: flex;align-items: center;justify-content: center;border: 1px dashed #d9d9d9;border-radius: 5px;padding: 20px;cursor: pointer;
}.upload-file {position: relative;margin-top: 10px;
}.upload-file image {border: 1px solid #d9d9d9;border-radius: 5px;
}.upload-file .u-icon {position: absolute;top: 5px;right: 5px;
}
</style>

5. utils/index.js 代码

import Compressor from 'compressorjs';export const getToken = () => uni.getStorageSync('token') || '';export const removeToken = () => uni.removeStorageSync('token');export const base64Encode = (str) => {// 将字符串转换为 UTF-8 编码的字节数组const utf8Bytes = new TextEncoder().encode(str);// 将字节数组转换为 Base64 字符串return btoa(String.fromCharCode.apply(null, utf8Bytes));
};export const base64Decode = (base64) => {// 将 Base64 字符串转换为字节数组const byteString = atob(base64);// 将字节数组转换为 UTF-8 字符串const bytes = new Uint8Array(byteString.length);for (let i = 0; i < byteString.length; i++) {bytes[i] = byteString.charCodeAt(i);}return new TextDecoder().decode(bytes);
};export const goPageByPath = (path, query = {}) => {if (!path) {throw new Error('缺少必须的path参数');}let queryLen = Object.keys(query).length;let queryStr = '';if (queryLen) {queryStr = Object.keys(query).map((key) => `${key}=${query[key]}`).join('&');queryStr = `?${queryStr}`;}uni.navigateTo({url: `${path}${queryStr}`});
};// 表单重置
export function resetForm(refName) {if (this.$refs[refName]) {this.$refs[refName].resetFields();}
}// 判断 是否是数字
export const isStrictNumber = (value) => {return typeof value === 'number' && !isNaN(value);
};// 获取文件的后缀名,不包含 .
export const getFileExt = (fileName) => {return fileName.split('.').pop();
};// 临时路径转file对象 针对h5端
export const tempFilePathToFile = ({tempFilePath, fileName}) => {if (!tempFilePath) {return Promise.resolve(null);}return new Promise(async (resolve, reject) => {try {const response = await fetch(tempFilePath);const blob = await response.blob();const mimeType = response.headers.get('content-type');const file = new File([blob], fileName, {type: mimeType});resolve(file);} catch (error) {resolve(null);}});
};// 压缩文件
export const compressFile = (file, options) => {return new Promise((resolve, reject) => {new Compressor(file, {...options,success(result) {resolve(result);},error(err) {reject(err);},});});
};

3. 总结说明

可能有更好的处理方式, 如果大家有更好的处理方式,可以在评论区,贴出代码,让播主也学习一下,学无止境

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

GPIO子系统中Controller驱动源码分析

往期内容 本专栏往期内容&#xff1a; Pinctrl子系统和其主要结构体引入Pinctrl子系统pinctrl_desc结构体进一步介绍Pinctrl子系统中client端设备树相关数据结构介绍和解析inctrl子系统中Pincontroller构造过程驱动分析&#xff1a;imx_pinctrl_soc_info结构体Pinctrl子系统中c…

【Linux系统编程】第四十二弹---多线程编程全攻略:涵盖线程创建、异常处理、用途、进程对比及线程控制

✨个人主页&#xff1a; 熬夜学编程的小林 &#x1f497;系列专栏&#xff1a; 【C语言详解】 【数据结构详解】【C详解】【Linux系统编程】 目录 1、线程创建 2、线程异常 3、线程用途 4、进程 VS 线程 5、线程控制 5.1、创建和等待线程 1、线程创建 线程能看到进程的大…

Qt入门基础分享

文章目录 学习 Qt 语言之前的基本知识1. 编程基础语法:面向对象编程(OOP):基本数据结构:了解数组、链表、栈、队列、树(如二叉树、平衡树)、图(如邻接矩阵、邻接表)等。算法:熟悉常见的排序算法(如快速排序、归并排序、冒泡排序)和查找算法(如线性查找、二分查找)…

超萌!HTMLCSS:超萌卡通熊猫头

效果演示 创建了一个卡通风格的熊猫头 HTML <div class"box"><div class"head"><div class"head-copy"></div><div class"ears-left"></div><div class"ears-right"></di…

使用 AMD GPU 的 ChatGLM-6B 双语语言模型

Using the ChatGLM-6B bilingual language model with AMD GPUs — ROCm Blogs 2024 年 4 月 4 日&#xff0c;作者&#xff1a; Phillip Dang. ChatGLM-6B 是一个开源的中英双语语言模型&#xff0c;拥有 62 亿参数。它基于通用语言模型 (GLM) 架构&#xff0c;针对中文对话进…

计算并联电阻的阻值

计算并联电阻的阻值 C语言代码C代码Java代码Python代码 &#x1f490;The Begin&#x1f490;点点关注&#xff0c;收藏不迷路&#x1f490; 对于阻值为r1和r2的电阻&#xff0c;其并联电阻阻值公式计算如下&#xff1a; R1/(1/r11/r2) 输入 两个电阻阻抗大小&#xff0c;浮…

创建线程时传递参数给线程

在C中&#xff0c;可以使用 std::thread 来创建和管理线程&#xff0c;同时可以通过几种方式将参数传递给线程函数。这些方法包括使用值传递、引用传递和指针传递。下面将对这些方法进行详细讲解并给出相应的代码示例。 1. 值传递参数 当你创建线程并希望传递参数时&#xff…

AAA 数据库事务隔离级别及死锁

目录 一、事务的四大特性&#xff08;ACID&#xff09; 1. 原子性(atomicity)&#xff1a; 2. 一致性(consistency)&#xff1a; 3. 隔离性(isolation)&#xff1a; 4. 持久性(durability)&#xff1a; 二、死锁的产生及解决方法 三、事务的四种隔离级别 0 .封锁协议 …

数字后端零基础入门系列 | Innovus零基础LAB学习Day9

Module 16 Wire Editing 这个章节的学习目标是学习如何在innovus中手工画线&#xff0c;切断一根线&#xff0c;换孔&#xff0c;更改一条net shape的layer和width等等。这个技能是每个数字IC后端工程师必须具备的。因为项目后期都需要这些技能来修复DRC和做一些手工custom走线…

前后端交互通用排序策略

目录 排序场景 排序实现思路 1. 静态代码排序实现 2.数据库驱动排序实现 3. 基于Java反射的动态排序实现 通用排序工具 SortListUtil 结语 排序场景 在面向前端数据展示的应用场景中&#xff0c;我们旨在实现一个更加灵活的排序机制&#xff0c;该机制能够支持对从后端传递…

前端入门一之CSS知识详解

前言 CSS是前端三件套之一&#xff0c;在MarkDown中也完美兼容这些语法&#xff1b;这篇文章是本人大一学习前端的笔记&#xff1b;欢迎点赞 收藏 关注&#xff0c;本人将会持续更新。 文章目录 Emmet语法&#xff1a;CSS基本语法&#xff1a;css语法结构只有3种&#xff1a…

leetcode | 88. 合并两个有序数组

题目描述 88. 合并两个有序数组 分析 题目不允许更改nums1的长度&#xff0c;要求原地更改。 题目其实不难&#xff0c;如果记住可以从后往前合并的解法&#xff0c;但是正向遍历的问题是什么呢&#xff1f; ——元素覆盖。那为什么负向遍历就不会有这个问题呢&#xff1f;…

跳蚤市场之商品发布功能

一 商品类别和小类的联动 以下是一个示例代码&#xff0c;展示了如何实现商品类别中大类和小类的联动。 商品大类选择框、小类选择框 的设计 html部分 <form id"category-form"><label for"major-category">大类&#xff1a;</label&g…

OpenAI 发布了新的事实性基准——SimpleQA

SimpleQA 简介 名为 SimpleQA 的事实性基准&#xff0c;用于衡量语言模型回答简短的事实性问题的能力。 人工智能领域的一个悬而未决的问题是如何训练模型&#xff0c;使其产生符合事实的回答。 目前的语言模型有时会产生错误的输出或没有证据证明的答案&#xff0c;这个问题…

Android camera2

一、序言 为了对阶段性的知识积累、方便以后调查问题&#xff0c;特做此文档&#xff01; 将以camera app 使用camera2 api进行分析。 (1)、打开相机 openCamera (2)、创建会话 createCaptureSession (3)、开始预览 setRepeatingRequest (4)、停止预览 stopRepeating (5)、关闭…

Javascript属性遮蔽问题

先了解一下Object.defineProperty()方法 Object.defineProperty() 静态方法会直接在一个对象上定义一个新属性&#xff0c;或修改其现有属性&#xff0c;并返回此对象。 //obj&#xff1a;要定义的对象 //prop&#xff1a;一个字符串或 Symbol&#xff0c;指定了要定义或修改…

vue3项目history模式部署404处理,使用 historyApiFallback 中间件支持单页面应用路由

vue3项目history模式部署404处理&#xff0c;使用 historyApiFallback 中间件支持单页面应用路由 在现代的 web 开发中&#xff0c;单页面应用&#xff08;SPA&#xff09;变得越来越流行。这类应用通常依赖于客户端路由来提供流畅的用户体验&#xff0c;但在服务器端&#xf…

【vim文本编辑器gcc编译器gdb调试器】

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 一、vimvim安装vim常用快捷键vim使用vimtutor zh文档 二、gcc编译器安装gcc工具编译源代码 三、gdb调试器gdb安装gdb常用指令gdb简单上手使用gdb的单步调试功能 总结…

企业数字化转型的架构治理策略:核心问题、深度分析与优化路径

在当今的商业环境中&#xff0c;企业数字化转型已成为实现可持续发展、增强竞争力的战略选择。企业架构治理&#xff08;Enterprise Architecture Governance Capability, EAGC&#xff09;在数字化转型中扮演着保障架构一致性、提升变革效能的关键角色。本指南深入解析了如何通…