uniapp 上传二进制流图片


场景

在这里插入图片描述

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

🟢一、步骤

在 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感兴趣的朋友,请多多关注💖💖💖,咱们一起探讨和努力!!!
👨‍🔧 个人主页 : 前端初见

### UniApp 小程序 文件流 上传 图片 实现方法 在 UniApp 中通过文件流的方式上传图片涉及到几个主要步骤,包括选择图片、读取图片作为数据流以及发送请求给服务器。以下是具体实现的方法: #### 使用 `uni.chooseImage` 方法选取图片 为了允许用户从相册或相机中选择图片,可以调用 `uni.chooseImage(OBJECT)` 函数来获取所选图像的信息。此函数返回的对象包含了本地临时路径和其他属性[^1]。 ```javascript // 调用 chooseImage 接口选择一张或多张图片 uni.chooseImage({ count: 1, // 默认9 sizeType: ['original', 'compressed'], // 可以指定是原图还是压缩图,默认二者都有 sourceType: ['album', 'camera'], // 可以指定来源是相册还是相机,默认二者都有 success: function (res) { const tempFilePaths = res.tempFilePaths; console.log('Selected image path:', tempFilePaths); // 进一步处理选定的图片... } }); ``` #### 创建 FormData 对象并加入图片文件 一旦获得了图片的临时路径之后,就需要创建一个 `FormData` 对象并将该对象用于封装要上传的数据。对于每一条记录来说,应该把对应的文件添加进去以便后续提交至服务器端。 ```javascript let formData = new FormData(); formData.append("file", {uri:tempFilePaths[0], name:"image.png", type:"image/png"}); ``` 需要注意的是,在某些情况下可能还需要设置额外参数比如文件名称 (`name`) 和 MIME 类型 (`type`) 来满足特定的服务端需求。 #### 发送 POST 请求携带二进制数据 最后一步就是利用合适的 HTTP 库(例如 axios 或者 fetch API),向目标 URL 地址发起带有上述构建好的表单数据体的 POST 请求。这里假设服务端已经配置好接收 multipart/form-data 形式的请求,并能够解析其中包含的文件内容。 ```javascript fetch('/upload-endpoint-url', { method: 'POST', body: formData, }).then(response => response.json()) .then(data => { console.log('Upload successful!', data); }).catch((error) => { console.error('Error during upload:', error.message); }); ``` 以上就是在 UniApp 小程序里采用文件流传输模式完成图片上载的过程概述[^2]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

前端初见

打赏一下,解锁更多有趣内容

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值