网站首页 > 技术文章 正文
领导:最近网络有点卡,图片加载的比较慢!
牛马:那咋办?
领导:你把图片都压缩一下,上传图片之前先压缩,能做到吗?
牛马:能(内心99个不愿意)
分析
后台的常规上传
一般做后台的比较多,后台的上传方式一般都是:
- 构建formData
- 传参,形如下图
其中的binary,一般都是一个file对象,里面包含了:文件名、大小、文件类型等
这样上传之后,后台会给我们返回对应的地址等信息
uni-app的上传
uni-app的上传和常规的后台不一样,uni-app自己封装了上传APIuni.uploadFile。
它的使用方法如下
uni.chooseImage({
success: (chooseImageRes) => {
const tempFilePaths = chooseImageRes.tempFilePaths;
uni.uploadFile({
url: 'https://www.example.com/upload', //仅为示例,非真实的接口地址
filePath: tempFilePaths[0],
name: 'file',
formData: {
'user': 'test'
},
success: (uploadFileRes) => {
console.log(uploadFileRes.data);
}
});
}
});
它只需要传filePath或者files对象数组。
其中的filePath是一个blob形式的本地url,形如:
blob:https://192.168.3.98:8080/704d5537-5849-4db6-9815-cc7efd8d8cf3
这个blob地址是可以本地临时访问的。
uni-app的上传形式和后台管理,看起来是一样的!
你要是这么以为,你就错了!
异同分析
相同点
上传格式:都是(具体和后台约定格式)
- file: (binary)
- folder: images
不同点
file的binary:
- 后台的是file文件对象
- uniapp的是blob地址字符串(files里的uri也是)
图片压缩
图片压缩可以用browser-image-compression库
yarn add browser-image-compression
简单封装一下压缩函数:
import imageCompression from 'browser-image-compression'
// 压缩图片
export async function compressImage(file) {
// 默认配置
const options = {
initialQuality: 0.5, // 压缩率
}
try {
let tempFile = await imageCompression(file, options)
// 创建一个新的 File 对象
const newFile = new File([tempFile], file.name, {
type: tempFile.type,
})
return newFile;
} catch (error) {
console.error('压缩图片失败', error)
return file
}
}
我们现在可以得到compressImage压缩后的file对象,然后把它转为blob地址就行了,这不就成功了吗
把上面的函数里的newFile转化一下
const blobUrl = URL.createObjectURL(newFile)
然后这个值就是filePath的值了,也就是下面的方法二:
uni.uploadFile({
url: baseUrl + '/file/upload', //真实的接口地址
// filePath: myUploadFile.path, // 方法一:原版的直接传blob路径
filePath: await compressImage(myUploadFile.file), // 方法二:压缩后再转为blob路径
name: 'file',
header: { Authorization: 'Bearer ' + getToken() },
formData: { folder: 'images' },
success: (_data) => {
console.log('上传成功返回:', _data.data)
},
fail: (res) => {
console.log('上传失败', res)
},
})
于是我兴冲冲地试了一下,图片大小果然压缩了50%,而且不影响清晰度,但是,图片名称怎么没了,名称可是需要显示的呀!!!
于是我又看向代码,uni-app也没传文件名称啊,怎么它的就能显示名称,我压缩之后的就不能显示名称呢?
原因
于是,我问了AI的解决方案,AI给了我2个解决方案:
- 在formData中加文件名name,或者files里加name;
- 明文传参文件名称,后端加上文件名称解析;
第一种方案是不合理的,我们尝试一下,如果你在formData中传name,是这样的
如果用files的方式传,结果是这样的,直接把file给覆盖了
第二种方案呢需要后端改动,显然不合理,因为之前的后台就可以直接传,也能直接返回文件名称……
等等,为什么后台的可以,而uni-app的却不可以呢?他们用的是同一个接口呀。
改造之路
上面其实已经有对比了,后台传的file对象的binary格式,uni-app传的是bloburl的字符串地址格式的binary,所以,我只要改造一下不就好了吗。
小插曲,我问了AI为什么uni-app上传的file都是blob url字符串地址,原版的就可以解析出名称,而压缩后的就无法解析呢?
AI回答:uni-app的uploadFile函数,底层做了自动处理,自动把名称以某种对应方式传过去了,而你压缩后的blob地址,就无法自动处理,也就没有名称了
于是,我就准备用uni.request重新封装,构建formData,在formData里传入压缩后的file对象,就像后台的处理方式一样,可是又报错了,因为uni.request请求的data参数不支持formData格式的
这下麻爪了,最后我就想,干脆我连请求都不用你的uni.request了,限制这么多,直接用原始的XMLHttpRequest构建封装请求,重新封装的代码如下:
// 创建 FormData 对象
const formData = new FormData();
formData.append('file', await compressImage(toUploadArr[i].file));
formData.append('folder', 'images');
// 使用 XMLHttpRequest 手动发送请求
const xhr = new XMLHttpRequest();
xhr.open('POST', baseUrl + '/file/upload', true);
xhr.setRequestHeader('Authorization', 'Bearer ' + getToken());
xhr.onload = () => {
if (xhr.status === 200) {
// 提示上传成功等操作
} else {
uni.showToast({ title: '上传失败', icon: 'none' });
}
};
xhr.onerror = () => {
this.$modal.closeLoading();
this.fileLists.pop();
uni.showToast({ title: '上传失败', icon: 'none' });
};
xhr.send(formData);
看下效果,改造后的确实能正确返回文件名称了,而且也确实是压缩过了的:
打完收工!
往期文章推荐
《若依ruoyi全栈(nodejs + vue3)+ AI助手,前端表示很香》
《若依Nodejs后台、实现90%以上接口,附体验地址、源码、拓展特色功能》
《vue3怎么和大模型交互?》
《前端怎么测网速?》
猜你喜欢
- 2025-05-28 想高效办公畅饮下午茶?这些显示器你肯定需要
- 2025-05-28 这样优化项目, 让公司的网站直接秒开,老板说给我加奖金
- 2025-05-28 我做了个 AI 神器,模糊图片变清晰,4倍无损放大,极简且好用
- 2025-05-28 「前端纯干货」原来TinyPNG可以这样玩
- 2025-05-28 前端面试-Web Worker:让你的网页不再“卡到崩溃”的秘诀
- 2025-05-28 Tinypng - 比ps更厉害的免费图片压缩神器
- 2025-05-28 深入JavaScript教你内存泄漏如何防范
- 2025-05-28 推荐三款正则可视化工具「JS篇」
- 2025-05-28 从零到一:小程序设计新手如何快速上手?
- 2025-05-28 PHP(gzdeflate/gzinflate)+JS(pako)前后端数据压缩
你 发表评论:
欢迎- 05-30为什么说网上的md5加密解密站都是通过彩虹表解密的?
- 05-30一文读懂md5,md5有什么用,什么是md5加盐
- 05-30Java md5加密解密数据
- 05-30MD5是什么?如何进行MD5校验?
- 05-30专家教你简单又轻松的MD5解密方法,一看就会
- 05-30多学习才能多赚钱之:vscode怎么安装插件
- 05-30VSCode无限画布模式(可能会惊艳到你的一个小功能)
- 05-30VSCode神级Ai插件Cline:从安装到实战【创建微信小程序扫雷】
- 最近发表
- 标签列表
-
- 前端设计模式 (75)
- 前端性能优化 (51)
- 前端模板 (66)
- 前端跨域 (52)
- 前端缓存 (63)
- 前端react (48)
- 前端aes加密 (58)
- 前端脚手架 (56)
- 前端md5加密 (54)
- 前端路由 (55)
- 前端数组 (65)
- 前端定时器 (47)
- Oracle RAC (73)
- oracle恢复 (76)
- oracle 删除表 (48)
- oracle 用户名 (74)
- oracle 工具 (55)
- oracle 内存 (50)
- oracle 导出表 (57)
- oracle 中文 (51)
- oracle链接 (47)
- oracle的函数 (57)
- mac oracle (47)
- 前端调试 (52)
- 前端登录页面 (48)
本文暂时没有评论,来添加一个吧(●'◡'●)