【Vue2】Vant2上传文件使用formData方式,base64图片转Blob再转File上传

news2025/1/12 23:12:09

文章目录

  • 前言
  • 一、base64转换为 Blob 对象的方法
  • 二、使用步骤
    • 1.引入工具类js
    • 2.编写formData上传方法
    • 3.api方法中的request代码
  • 三、实际操作
    • 1.html代码
    • 2.js代码
  • 总结


前言

vant2上传组件传送门
使用vant2组件中的uploader组件

<van-uploader v-model="fileList" multiple capture :after-read="afterRead" @delete="onDelete" />

提示:以下是本篇文章正文内容,下面案例可供参考

一、base64转换为 Blob 对象的方法

在utils文件夹下,创建一个工具类js,名叫base64toFile.js

// 转换为 Blob 对象的方法 (可复用)
export function base64ToBlob(base64Data) {
    const parts = base64Data.split(";base64,");
    const contentType = parts[0].split(":")[1];
    const raw = window.atob(parts[1]);
    const rawLength = raw.length;
    const uInt8Array = new Uint8Array(rawLength);
    for (let i = 0; i < rawLength; ++i) {
        uInt8Array[i] = raw.charCodeAt(i);
    }
    return new Blob([uInt8Array], { type: contentType });
}
// 从 base64 数据中获取文件名和 mime 类型的方法 (可复用)
export function getFilenameAndMimetypeFromBase64(base64Data) {
    const fileInfo = base64Data.split(';base64,')[0].substring(5).split(':');
    const mimeType = fileInfo[0];
    const filename = fileInfo[1];
    return [filename, mimeType];
}
/**
 *  用法
// 将 base64 编码的文件数据转为 Blob 对象
const blob = base64ToBlob(res);
// 获取文件名和 mime 类型
const [filename, mimeType] = getFilenameAndMimetypeFromBase64(res);
// 将 Blob 对象转换为 File 对象
const file = new File([blob], filename, { type: mimeType });
// 上传文件
const formData = new FormData();
formData.append('file', file);

axios.post('/api/upload', formData, {
  headers: {
    'Content-Type': 'multipart/form-data'
  }
}).then(response => {
  console.log(response.data);
}).catch(error => {
  console.log(error);
});
 */

用法在上面代码里有,也就是后面的过程

二、使用步骤

1.引入工具类js

代码如下(示例):

import {
    base64ToBlob,
    getFilenameAndMimetypeFromBase64
} from "@/utils/base64toFile.js"

2.编写formData上传方法

src/api里面的某一个文件夹里面编写你的上传
在这里插入图片描述

代码如下(示例):

import request from '@/utils/request'
// 上传图片
export function uploadImg(data) {
    return request({
        url: '/flow/common/upload',
        method: 'post',
        headers: {
            'Content-Type': 'multipart/form-data'
        },
        data: data
    })
}

根据实际情况修改url地址,

3.api方法中的request代码

在utils工具文件夹中新建request.js

import axios from 'axios'
import errorCode from '@/utils/errorCode'
import {
	getToken
} from '@/utils/auth'
import {
	Dialog,
	Notify
} from 'vant';
axios.defaults.headers['Content-Type'] = 'application/json;charset=utf-8'

// 创建axios实例
const service = axios.create({
	// axios中请求配置有baseURL选项,表示请求URL公共部分
	// baseURL: '/',
	baseURL: process.env.VUE_APP_BASE_API,
	// 超时
	timeout: 40000
})
// request拦截器
service.interceptors.request.use(config => {
	// 是否需要设置 token
	const isToken = (config.headers || {}).isToken === false
	// config.headers['Authorization'] = sessionStorage.getItem('token') // 让每个请求携带自定义token 请根据实际情况自行修改
	// config.headers['token'] = sessionStorage.getItem('token') // 让每个请求携带自定义token 请根据实际情况自行修改
	config.headers['Authorization'] = 'Bearer ' + getToken()
	// get请求映射params参数
	if (config.method === 'get' && config.params) {
		let url = config.url + '?';
		for (const propName of Object.keys(config.params)) {
			const value = config.params[propName];
			var part = encodeURIComponent(propName) + "=";
			if (value !== null && typeof (value) !== "undefined") {
				if (typeof value === 'object') {
					for (const key of Object.keys(value)) {
						let params = propName + '[' + key + ']';
						var subPart = encodeURIComponent(params) + "=";
						url += subPart + encodeURIComponent(value[key]) + "&";
					}
				} else {
					url += part + encodeURIComponent(value) + "&";
				}
			}
		}
		url = url.slice(0, -1);
		config.params = {};
		config.url = url;
	}
	return config
}, error => {
	console.log(error)
	Promise.reject(error)
})
// 响应拦截器
service.interceptors.response.use(res => {
	// 未设置状态码则默认成功状态
	const code = res.data.code || 200;
	// 获取错误信息
	const msg = errorCode[code] || res.data.msg || errorCode['default']
	// 二进制数据则直接返回
	if (res.request.responseType === 'blob' || res.request.responseType === 'arraybuffer') {
		return res.data
	}
	if (code === 401) {
		return Promise.reject('无效的会话,或者会话已过期,请重新登录。')
	} else if (code === 402) {
		Dialog.alert({
			message: res.data.msg,
			confirmButtonColor: "#3478F3",
		}).then(() => {

		});
		return Promise.reject(new Error(msg))
	} else if (code === 403) {
		return Promise.reject(new Error(msg))
	} else if (code === 500) {
		Notify({
			type: 'danger',
			message: msg
		});
		return Promise.reject(new Error(msg))
	} else if (code === 601) {
		Notify({
			type: 'warning',
			message: msg
		});
		return Promise.reject('error')
	} else if (code !== 200) {
		Dialog({
			title: '错误',
			message: msg
		});
		return Promise.reject('error')
	} else {
		return res.data
	}
},
	error => {
		console.log('err' + error)
		let {
			message
		} = error;
		if (message == "Network Error") {
			message = "后端接口连接异常";
		} else if (message.includes("timeout")) {
			message = "系统接口请求超时";
		} else if (message.includes("Request failed with status code")) {
			message = "系统接口" + message.substr(message.length - 3) + "异常";
		}
		Notify({
			message: message,
			type: 'danger',
			duration: 5 * 1000,
		});
		return Promise.reject(error)
	}
)
export default service

request.js有许多的工具类引入,不过一般的vue项目应该都有脚手架,如果没有的,或者没见过这个request.js的,可以去翻一下若依后台管理系统的源码。这里只作示例,告知请求方法中的封装是这些代码


三、实际操作

1.html代码

<van-uploader v-model="fileList" multiple capture :after-read="afterRead" @delete="onDelete" />

2.js代码

import方法

import {
    base64ToBlob,
    getFilenameAndMimetypeFromBase64
} from "@/utils/base64.js"
import {
    uploadImg, // 上传拍照的图片
} from "@/api/upload.js"

data变量

fileList: [],

methods方法

afterRead(res) {
    // 此时可以自行将文件上传至服务器
    console.log(res, "file");
    // base64格式赋值, data:image/jpeg;base64,/9j.......
    const data = res.content
    // 将 base64 编码的文件数据转为 Blob 对象
    const blob = base64ToBlob(data);
    // 获取文件名和 mime 类型
    const [filename, mimeType] = getFilenameAndMimetypeFromBase64(data);
    // 将 Blob 对象转换为 File 对象
    const file = new File([blob], res.file.name, { type: mimeType });
    // 写入formData
    const formData = new FormData();
    formData.append('file', file);
    // 执行上传方法
    uploadImg(formData).then(res => {
        console.log(res, "上传结果", this.fileList);
        this.form.files.push(res.data) // 写入form参数
    })
},

afterRead为vant组件 上传模块的回调
它的回调参数的content是一个base64图片 data:image/jpeg;base64,/9j.......

这段代码的文件名有可能会拿不到,毕竟是base64图片文件,所以filename可以自己定义,
在这里插入图片描述

// 获取文件名和 mime 类型
const [filename, mimeType] = getFilenameAndMimetypeFromBase64(res);
// 将 Blob 对象转换为 File 对象
const file = new File([blob], filename, { type: mimeType });

总结

除了base64格式的文件,可以用formData方式上传,别的例如文档doc、pdf也可以。
只要选择文件上传,拿到的回调参数里面,有一个是file类型的,那就是这个。
把这个file添加到formData,然后也是一样的上传。
如下

<el-dialog :title="upload.title" :visible.sync="upload.open" width="400px" append-to-body>
    <el-upload class="upload-demo" :file-list="uploadFileList" drag
     :on-change="getFiles" 
    :on-remove="getFiles"
        action="" :auto-upload="false" multiple>
        <i class="el-icon-upload"></i>
        <div class="el-upload__text">将文件拖到此处,或<em>点击上传</em></div>
        <div class="el-upload__tip" slot="tip">只能上传jpg/png文件,且不超过500kb</div>
    </el-upload>
    <div slot="footer" class="dialog-footer">
        <el-button type="primary" @click="submitFileForm">确 定</el-button>
        <el-button @click="upload.open = false">取 消</el-button>
    </div>
</el-dialog>
// 提交上传文件
submitFileForm() {
    let formData = new FormData();
    this.files.forEach(f => formData.append("files", f.raw))
    fileUpload(formData).then(res => {
        this.$modal.msgSuccess("上传成功")
    })
    this.upload.open = false;
},
getFiles(file, fileList) {
    this.files = fileList;
},

在这里插入图片描述

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

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

相关文章

打破常规之路,创新永不停歇!ADSCOPE成功斩获2023第十一届TopDigital“年度最佳营销技术公司”奖项!

2023年6月29日&#xff0c;第十一届TopDigital创新营销奖获奖结果正式揭晓&#xff0c;ADSCOPE凭借先进的广告变现技术&#xff0c;创新的变现理念&#xff0c;从海内外657家参赛企业提交的3052件作品中突出重围&#xff0c;成功斩获“TopDigital创新营销奖—年度最佳营销技术公…

el-table多级表头处理方法,了解lebel和prop的真实含义,template的意义,减少全局定义变量。

Element - The worlds most popular Vue UI framework 官网地址 其原理只需要在 el-table-column 里面嵌套 el-table-column&#xff0c;就可以实现多级表头。 要实现的效果如下图所示&#xff1a; <div class"c-table" id"tablePrint"><el-tabl…

【Java-SpringBoot+Vue+MySql】前后端分离项目云端部署

目录 部署环境&#xff1a; 安装MYSQL&#xff1a; 安装Nginx 安装配置JDK 远程连接数据库 前端打包 后端打包 心得&#xff1a; 部署环境&#xff1a; CentOS7.6 MySQL5.7 JDK1.8 Nginx1.8 下载MySQL MySQL :: Download MySQL Community Server (Archived Versions) …

qt Qss 边框渐变

目录 背景渐变 方案一 Qss 方案二 paintEvent函数 方案三 QGraphicsDropShadowEffect投影效果 背景渐变 QT里面背景是可以渐变&#xff0c;其中qlineargradient里面参数意思 spread&#xff1a;渐变方式&#xff08;具体可以查看qt帮助文档搜索PadSpread&#xff09; 坐…

vue2模拟无限级评论

目录 一、效果展示 二、代码展示 2.1、主页面 2.2、评论父页面组件 2.3、评论多级页面(递归组件) 一、效果展示 二、代码展示 2.1、主页面 <template><div><h1>姓名:{{ $store.state.userInfo1.username }}</h1><button:class"{ aacti…

【加密算法】5 种常见的摘要、加密算法

大家平时的工作中&#xff0c;可能也在很多地方用到了加密、解密&#xff0c;比如&#xff1a; 用户的密码不能明文存储&#xff0c;要存储加密后的密文用户的银行卡号、身份证号之类的敏感数据&#xff0c;需要加密传输还有一些重要接口&#xff0c;比如支付&#xff0c;客户…

数据结构和算法的概念以及时间复杂度空间复杂度详解

⭐️ 什么是数据结构&#xff1f; 百度百科给数据结构的定义&#xff1a; 数据结构(Data Structure)是计算机存储、组织数据的方式。数据结构是指相互之间存在一种或多种特定关系的数据元素的集合。 数据结构就是数据在内存中的存储方式。 ⭐️ 什么是算法&#xff1f; 百度百…

基于高精度三维机器视觉的新能源汽车锂电池表面缺陷检测

​Part.1 行业背景 ​随着新能源汽车在全球范围内成为焦点发展领域&#xff0c;企业对电池质量控制和检测的要求也变得更加严格。在机器视觉行业迅速发展的背景下&#xff0c;市场上提供了功能强大且种类齐全的3D相机系列&#xff0c;可以满足锂电池从电芯到模组各个工艺和工位…

IAM风险CTF挑战赛

wiz启动了一个名为“The Big IAM Challenge”云安全CTF挑战赛。旨在让白帽子识别和利用 IAM错误配置&#xff0c;并从现实场景中学习&#xff0c;从而更好的认识和了解IAM相关的风险。比赛包括6个场景&#xff0c;每个场景都专注于各种AWS服务中常见的IAM配置错误。 Challenge…

【Docker】云原生利用Docker确保环境安全、部署的安全性、安全问题的主要表现和新兴技术产生的详细讲解

前言 Docker 是一个开源的应用容器引擎&#xff0c;让开发者可以打包他们的应用以及依赖包到一个可移植的容器中,然后发布到任何流行的Linux或Windows操作系统的机器上,也可以实现虚拟化,容器是完全使用沙箱机制,相互之间不会有任何接口。 &#x1f4d5;作者简介&#xff1a;热…

Vue键盘事件

1.Vue中常用的按键别名&#xff1a; 回车enter 删除delete&#xff08;捕获“删除”和“退格”键&#xff09; 推出esc 空格space 换行tab&#xff08;特殊&#xff0c;必须配合keydown使用&#xff09; 上up 下down 左left 右right 2.Vue未提供别名的按键&#xff0c;可以使用…

Arduino驱动BH1750模块实现光照强度采集

Arduino驱动BH1750模块实现光照强度采集 简介特征电气参数接线程序结果 简介 BH1750FVI是一个用于I2 C总线接口的数字环境光传感器IC。该IC最适合于获取调节手机液晶显示屏和键盘背光功率的环境光数据。在高分辨率下探测大范围是可能的。(1 - 65535 lx )。BH1750FVI可以应用于…

Matlab 回归分析与预测

统计分析 回归分析与预测 数理统计—回归分析 回归分析类型 回归分析目的 一元线性回归 多元线性回归的案例 %{ [B,BINT,R,RINT,STATS] regress(Y,X) [B,BINT,R,RINT,STATS] regress(Y,X,ALPHA) 参数解释&#xff1a;B&#xff1a; 回归系数&#xff0c;是个向量&…

小程序官方tabbar和自定义tabbar

uniapp官方tabbar&#xff1a; 打开项目中的 pages.json 文件。 在 JSON 对象中添加一个名为 tabBar 的字段&#xff0c;并设置其值为一个对象。 在 tabBar 对象中&#xff0c;配置 color 和 selectedColor 字段来定义 TabBar 的默认颜色和选中项的颜色。示例&#xff1a; …

功放IC 2018和功放IC HX8358A的区别

概述&#xff1a; 2018功放IC&#xff0c;目前在市面的情况是品牌多、杂&#xff0c;芯片的工作电压和喇叭输出功率不统一。经常出现低电压芯片用在高电压的产品上面&#xff0c;导致芯片容易损坏&#xff0c;给用户带来一定的麻烦。但它的销售量可能已超过8002的功放芯片了&am…

6.19、JAVA IO流 File 字节流 字符流

IO简介 1 流Stream 在学习IO流之前,我们首先需要学习的概念就是Stream流 为了方便理解,我们可以把数据的读写操作抽象成数据在"管道"中流动,但需注意: 1.流只能单方向流动 2.输入流用来读取 → in 3.输出流用来写出 → out 4.数据只能从头到尾顺序的读写一次 所以以…

Python 基本数据类型(六)

文章目录 每日一句正能量Tuple&#xff08;元组&#xff09;结语 每日一句正能量 一生要做的几件事情一管理好自己的身体。二管理好自己的情绪&#xff0c;正面思维。三服务好自己的家庭&#xff0c;让家人生活幸福。四做好本职工作&#xff0c;做一两件特别完美&#xff0c;石…

剑指 Offer 51: 数组中的逆序对

这道题归根结底就是一个归并问题&#xff0c;逆序对本质上就是比较大小&#xff0c;如果两边作为一个整体比较过那么就可以排序合并&#xff08;因为这个过程每一步都计算了count的值&#xff0c;所以合并起来是可以的&#xff09;。 下面的k应该是mid1&#xff08;从中间的右…

智“绘“城市:智慧环卫可视化运营管理系统

前言 随着我国城镇化的不断推进&#xff0c;城市的规模、数量不断增加&#xff0c;城市的人口数量也快速增长&#xff0c;造成的城镇生活垃圾、建筑垃圾也随之增长&#xff0c;这造成人们对环卫服务的需求增加。而与此同时&#xff0c;随着经济社会的快速发展&#xff0c;人们…

ChatGLM-6B微调p tuning v2和lora对比

官方项目地址&#xff1a;https://github.com/THUDM/ChatGLM-6B 参考本人之前的博客下载ChatGLM-6B模型&#xff1a; https://blog.csdn.net/Acecai01/article/details/131221676 设备 一张3090Ti&#xff0c; 24G显卡 实验目的 通过微调的方法&#xff0c;训练ChatGLM-6B模…