uniapp 上传二进制流图片

news2025/7/19 12:12:53

文章目录

  • 场景
  • 🟢一、步骤
    • 1.1、选择图片
    • 1.2、 读取图片为二进制数据
    • 1.3、上传二进制数据到服务器
  • 🟢二、项目案例
    • 2.1、替换头像案例
    • 2.1、uView u-upload 上传封面
  • 🟢 三、关键注意事项
    • 3.1 二进制流与 FormData 区别
    • 3.2 性能优化
    • 3.3 跨平台适配
  • ✒️总结


场景

在这里插入图片描述

在日常开发中,常需实现用户头像更换、图片附件上传等功能。通过将图片转换为二进制流上传,可灵活适配不同后端接口需求,本文将详细介绍具体实现步骤及项目案例。

🟢一、步骤

在 UniApp 中上传二进制流图片,一般需要经过选择图片、读取为二进制数据、上传二进制数据到服务器这几个主要步骤

1.1、选择图片

使用 uni.chooseMedia 或 uni.chooseImage 方法让用户从相册或相机选择图片。
uni.chooseMedia(推荐,UniApp 3.1.0+ 支持)或 uni.chooseImage 调用系统媒体选择器。

uni.chooseMedia({
    count: 1, // 选择图片的数量
    mediaType: ['image'], // 只选择图片
    success: (res) => {
        const tempFilePath = res.tempFiles[0].tempFilePath;
        // 后续可将 tempFilePath 用于读取二进制数据
    },
    fail: (err) => {
        console.error('选择图片失败:', err);
    }
});

1.2、 读取图片为二进制数据

使用 uni.getFileSystemManager().readFile 方法将选择的图片文件读取为ArrayBuffer 格式二进制数据

uni.getFileSystemManager().readFile({
    filePath: tempFilePath,
    success: (fileRes) => {
        const binaryData = fileRes.data;
        // 后续可将 binaryData 用于上传
    },
    fail: (err) => {
        console.error('读取文件失败:', err);
    }
});

1.3、上传二进制数据到服务器

通过 uni.request 发送二进制流,需注意请求头设置为 application/octet-stream。

uni.request({
    url: 'https://xxx/upload', // 服务器上传接口地址
    method: 'POST',
    data: binaryData,
    headers: {
        'Content-Type': 'application/octet-stream'
    },
    success: (res) => {
        if (res.statusCode === 200) {
            console.log('上传成功:', res.data);
        } else {
            console.error('上传失败,状态码:', res.statusCode);
        }
    },
    fail: (err) => {
        console.error('上传失败:', err);
    }
});

🟢二、项目案例

2.1、替换头像案例

uni.chooseMedia+uni.getFileSystemManager().readFile方案实现

页面结构

	<view class="img-box" @click="onAvatatChange">
				<image mode="aspectFill" class="img" :src="addformData.avatar"></image>
				<view class="text">点击更换头像</view>
	</view>

逻辑实现

			// 修改头像
			onAvatatChange() {
				// 调用拍照/选择图片
				uni.chooseMedia({
					count: 1,
					mediaType: ['image'],
					success: (res) => {
						console.log(res.tempFiles[0].tempFilePath)
						const tempFilePath = res.tempFiles[0].tempFilePath;
						// 读取图片文件为二进制数据
						uni.getFileSystemManager().readFile({
							filePath: tempFilePath,
							success: (fileRes) => {
								const binaryData = fileRes.data;
								// 上传二进制数据到服务器
								this.uploadBinaryData(binaryData, tempFilePath);
							},
							fail: (err) => {
								console.error('读取文件失败:', err);
								uni.showToast({
									title: '读取文件失败',
									icon: 'none'
								});
							}
						});
					}
				})


			},
			uploadBinaryData(binaryData, tempFilePath) {
				uni.uploadFile({
					url: "https://xxxx/file/upload",
					method: 'POST',
					formData: binaryData,
					filePath: tempFilePath,
					name: "file",
					header: {
						'Authorization': uni.getStorageSync('token'),
						'Content-Type': 'multipart/form-data'
					},
					success: (res) => {
					
						let resut = JSON.parse(res.data)
						if (resut.code == 200) {
		
							this.addformData.avatar = resut.data.url
						}
				
					},
				})

			},
			
			

2.1、uView u-upload 上传封面

页面结构

<u-upload :fileList="fileList1" @afterRead="afterRead" @delete="deletePic" name="1" multiple
						:maxCount="1"></u-upload>

			// 删除图片
			deletePic(event) {
				console.log('删除', event)
				this.api.FileDelete({
					filePath: event.file.baseUrl
				}).then(res => {
					console.log('删除附件', res)
					uni.showToast({
						title: '删除成功',
						icon: 'success',
						duration: 1500
					});
					this[`fileList${event.name}`].splice(event.index, 1);

				})


			},
			// 新增图片
			async afterRead(event) {
				// 当设置 multiple 为 true 时, file 为数组格式,否则为对象格式
				let lists = [].concat(event.file);
				let fileListLen = this[`fileList${event.name}`].length;
				lists.map((item) => {
					this[`fileList${event.name}`].push({
						...item,
						status: "uploading",
						message: "上传中",
					});
				});
				for (let i = 0; i < lists.length; i++) {
					const result = await this.uploadFilePromise(lists[i]);
					let item = this[`fileList${event.name}`][fileListLen];
					this[`fileList${event.name}`].splice(
						fileListLen,
						1,
						Object.assign(item, {
							status: "success",
							message: "",
							url: result.url,
							name: result.name,
							baseUrl: result.baseUrl,
						})
					);
					fileListLen++;
				}
			},
			//上传图片
			uploadFilePromise(file) {
				console.log('file', file)
				return new Promise((resolve, reject) => {
					uni.getFileSystemManager().readFile({
						filePath: file.url,
						encoding: 'binary',
						success: (readRes) => {
							console.log('readRes', readRes)
							console.log('文件内容长度:', readRes.data.length);
							uni.uploadFile({
								// url: "http://xxx/file/upload", // 仅为示例,非真实的接口地址
								url: "https://xxxx/file/upload", // 仅为示例,非真实的接口地址
								filePath: file.url,
								name: "file",
								// header: {
								// 	'Authorization': uni.getStorageSync('token'),
								// 	'Content-Type': 'application/octet-stream'
								// },
								header: {
									// 添加请求头
									'Authorization': uni.getStorageSync('token'),
									// 可以添加其他请求头
									'Content-Type': 'multipart/form-data'
								},
								formData: readRes,
								// formData: {
								// 	user: "test",
								// },
								success: async (res) => {

									console.log('res文件上传', res)
									setTimeout(() => {
										resolve(JSON.parse(res.data).data);
										uni.showToast({
											title: '上传成功',
											icon: 'success',
											duration: 1500
										});
									}, 1000);
								},
								fail: (err) => {
									reject(err);
								}
							});
						},
						fail: (err) => {
							reject(err);
						}
					});
				});
			},
         
		
		

🟢 三、关键注意事项

3.1 二进制流与 FormData 区别

方式适用场景请求头设置后端
二进制流纯文件字节流传输Content-Type: application/octet-stream直接读取请求体字节数据
FormData 封装需附带其他字段(如业务参数)Content-Type: multipart/form-data通过 file 字段解析文件

3.2 性能优化

  • 压缩图片:上传前通过 uni.compressImage 压缩图片,减少传输数据量。
  • 并行上传:使用 Promise.all 并行处理多图上传(需注意服务器接口是否支持)。
  • 进度监听:通过 uni.uploadFileonProgressUpdate 回调显示上传进度条。

3.3 跨平台适配

  • 小程序平台uni.chooseMedia 自动适配微信/支付宝/字节等小程序的图片选择接口。
  • H5 平台:需确保服务器支持跨域请求(设置 Access-Control-Allow-Origin)。
  • App 平台:需在 manifest 中配置文件读写权限(FS_WRITE_ACCESS)。

✒️总结

UniApp 中上传二进制流图片的核心在于:

  1. 通过 uni.chooseMediauni.chooseImage 获取图片临时路径;
  2. 使用文件系统 API 读取为二进制数据;
  3. 根据后端要求选择 uni.request(二进制流)或 uni.uploadFile(FormData 表单)上传。

实际开发中,建议优先使用 uni.chooseMedia 统一跨平台体验,并根据接口规范灵活设置请求头。对于复杂场景(如多图上传、进度显示),可结合组件库(如 uView)或自定义指令优化交互体验。

如果本文对你有帮助,欢迎点赞支持!如需进一步探讨前端或 UniApp 开发,可访问我的个人主页「前端初见」,期待与你共同成长!

如果这篇【文章】有帮助到你💖,希望可以给我点个赞👍,创作不易,如果有对前端端或者对python感兴趣的朋友,请多多关注💖💖💖,咱们一起探讨和努力!!!
👨‍🔧 个人主页 : 前端初见

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

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

相关文章

赛灵思 XCKU115-2FLVB2104I Xilinx Kintex UltraScale FPGA

XCKU115-2FLVB2104I 是 AMD Xilinx Kintex UltraScale FPGA&#xff0c;基于 20 nm 先进工艺&#xff0c;提供高达 1 451 100 个逻辑单元&#xff08;Logic Cells&#xff09;&#xff0c;77 721 600 bit 的片上 RAM 资源&#xff0c;以及 5 520 个 DSP 切片&#xff08;DSP48E…

Unreal Niagara制作SubUV贴图翻页动画

SubUV翻页动画是游戏中的常见功能&#xff0c;通过对每一小块UV进行移动可以模拟动画效果&#xff0c;接下来对下图进行SubUV动画的制作。 (金币测试图下载地址&#xff1a;https://download.csdn.net/download/grayrail/90684422&#xff09; 最终效果如下&#xff1a; 1.…

「零配置陷阱」:现代全栈工具链的复杂度管控实践

一、工具链膨胀的「死亡螺旋」 2024年典型全栈项目的初始化噩梦&#xff1a; $ npm create vitelatest ✔ Project name: … demo ✔ Select a framework: › React ✔ Select a variant: › TypeScript SWC ✔ Install shadcn/ui? … Yes ✔ Add Storybook? … Yes ✔ Co…

金仓数据库KingbaseES技术实践类深度剖析与实战指南

一、语法兼容及迁移实战 &#xff08;一&#xff09;语法兼容的多元魅力 在当今多元化的数据库应用环境中&#xff0c;金仓数据库管理系统KingbaseES凭借其卓越的语法兼容能力脱颖而出。它采用的融合数据库架构&#xff0c;通过多语法体系一体化架构&#xff0c;实现了对Orac…

基于ssm的个人博客管理系统(源码+数据库+万字文档)

57基于ssm的个人博客管理系统&#xff1a;前端jsp、jquery、easyui&#xff0c;后端 spring、mybatis、maven&#xff0c;集成个人博客浏览、详情查看、博客发布、富文本编辑、评论等功能于一体的系统。 ## 功能介绍 ### 用户 - 首页&#xff1a;博客列表、博客详情、关键词…

综述 | GUI Agent:让AI学会「玩手机」的新革命

想象一下&#xff0c;你的手机里住着一个隐形助理&#xff1a;你说“把亮度调到50%”&#xff0c;它自动操作&#xff1b;你说“下载最新游戏”&#xff0c;它一键完成。这就是GUI智能体——一种能“看懂”屏幕并操作的AI。 论文&#xff1a;A Survey on (M)LLM-Based GUI Agen…

Canvas入门教程!!【Canvas篇二】

没有一朵花&#xff0c;从一开始就是花。 目录 translate() 方法&#xff1a;rotate() 方法&#xff1a;scale() 方法&#xff1a; translate() 方法&#xff1a; Canvas 2D API 的 CanvasRenderingContext2D.translate() 方法用于对当前网格添加平移变换。 translate() 方法通…

【中级软件设计师】函数调用 —— 传值调用和传地址调用 (附软考真题)

【中级软件设计师】函数调用 —— 传值调用和传地址调用 (附软考真题) 目录 【中级软件设计师】函数调用 —— 传值调用和传地址调用 (附软考真题)一、历年真题二、考点&#xff1a;函数调用 —— 传值调用和传地址调用&#x1f53a;1、传值调用&#x1f53a;2、传引用(地址)调…

第七届能源系统与电气电力国际学术会议(ICESEP 2025)

重要信息 时间&#xff1a;2025年6月20-22日 地点&#xff1a;中国-武汉 官网&#xff1a;www.icesep.net 主题 能源系统 节能技术、能源存储技术、可再生能源、热能与动力工程 、能源工程、可再生能源技术和系统、风力发…

大数据分析04 数据查询分析

构建数据源 引入pandas包 数据map中ID为列&#xff0c;值为行&#xff0c;每一列中值个数要一致 import pandas as pd data {ID: [000001, 000002, 000003, 000004, 000005, 000006, 000007],name:[黎明, 赵怡春, 张富平, 白丽, 牛玉德, 姚华, 李南], gender:[True, False, …

ADVB协议同步

关于视频传输&#xff0c;有多种控制时序。协议标准允许设计者选择有限的几个速率的接口来满足 系统设计目标。例如&#xff0c;一些系统使用总线时序发送信息通过line-by-line;在这个案例中&#xff0c; 容器的sof作为vsync同步的点。horizontal line blanding将插入idles,ADV…

【kafka初学】启动执行命令

接上篇&#xff0c;启动&#xff1a;开两个cdm窗口 注意放的文件不要太深或者中文&#xff0c;会报命令行太长的错误 启动zookeeper bin\windows\zookeeper-server-start.bat config\zookeeper.properties2. 启动kafka-serve bin\windows\kafka-server-start.bat config\serv…

论文阅读笔记——π0.5: a Vision-Language-Action Model with Open-World Generalization

π0.5 论文 通过异构数据协同训练与分层推理&#xff0c;用中等规模的目标数据&#xff08;400小时&#xff09;实现了大规模泛化能力&#xff0c;为现实世界机器人学习提供了新范式。 高层推理(high-level) 根据当前观测和任务指令预测子任务&#xff08;如“打开抽屉”&…

电子削铅笔刀顺序图详解:从UML设计到PlantUML实现

题目&#xff1a;为电子削铅笔刀建立一个顺序图和一个通信图。图中的对象包括操作者、铅笔、插入点(也就是铅笔插入铅笔刀的位置)、马达和其他元素。包括哪些交互消息?有那些激活?如何在图中表示出自身调用。 一、顺序图概述 顺序图&#xff08;Sequence Diagram&#xff09…

FWFT_FIFO和Standard_FIFO对比仿真

在FPGA中使用FIFO时&#xff0c;如果使用FPGA厂商提供的FIFO IP&#xff0c;一般都会有First Word Fall Through FIFO和Standard FIFO类型选项&#xff0c;那么这两种FIFO有什么差异么。两种FIFO的端口是一样的&#xff0c;看不出区别&#xff0c;只有通过仿真&#xff0c;才能…

什么是可重入锁ReentrantLock?

大家好&#xff0c;我是锋哥。今天分享关于【什么是可重入锁ReentrantLock?】面试题。希望对大家有帮助&#xff1b; 什么是可重入锁ReentrantLock? ReentrantLock 是 Java 中的一个锁实现&#xff0c;它是 java.util.concurrent.locks 包中的一部分&#xff0c;主要用于提供…

利用JMeter代理服务器方式实现高效压测

前言 在当今快节奏的互联网时代&#xff0c;确保Web应用和服务能够在高负载下稳定运行变得至关重要。无论是电子商务平台、社交媒体网络还是在线教育服务&#xff0c;用户对网站响应速度和稳定性的期望从未如此之高。因此&#xff0c;性能测试不再是一个可选项&#xff0c;而是…

WSL 安装过程整理

WSL 安装过程整理 一、WSL 安装教程二、安装后小技巧1、安装位置2、常用命令 三、在 WSL2 中安装 perf&#xff1a; 一、WSL 安装教程 史上最全的WSL安装教程 WSL2 最新最全帮助小白一步步详细安装教程 在WSL2 root 和普通用户的切换 轻松搬迁&#xff01;教你如何将WSL从C盘迁…

form表单提交前设置请求头request header及文件下载

需求&#xff1a;想要在form表单submit之前&#xff0c;设置一下请求头。 除了用Ajax发起请求之外&#xff0c;还可以使用FormData来实现&#xff0c;咱不懂就问。 1 问&#xff1a;FormData什么时间出现的&#xff1f;与ajax什么联系&#xff1f; 2 问&#xff1a;FormData使…

【c++11】c++11新特性(下)(可变参数模板、default和delete、容器新设定、包装器)

&#x1f31f;&#x1f31f;作者主页&#xff1a;ephemerals__ &#x1f31f;&#x1f31f;所属专栏&#xff1a;C 目录 前言 五、可变参数模板 1. 概念及简单定义 2. 包扩展 六、 default和delete 七、容器新设定 1. 新容器 2. 新接口 emplace系列接口 八、函数包…