前言
随着微信小程序的普及,图片上传已成为许多开发者关注的重点。在本文中,我们将探讨如何实现微信小程序的图片上传功能,帮助大家更好地应对开发中的挑战。
实现思路
首先我们需要定义一个存放图片的数组,通过方法拿取图片的详细信息,然后调用微信小程序的 wx.uploadFile
方法将拿到的图片信息添加到定义好的图片数组中即可;删除图片我们只需要拿到存放图片的数组再通过 splice
方法删除。
wx.uploadFile(Object object) 方法的参数:
属性 | 类型 | 必填项 | 说明 |
---|---|---|---|
url | string | 是 | 开发者服务器地址 |
filePath | string | 是 | 要上传文件资源的路径 (本地路径) |
name | string | 是 | 文件对应的 key,开发者在服务端可以通过这个 key 获取文件的二进制内容 |
header | Object | 否 | HTTP 请求 Header,Header 中不能设置 Referer |
formData | Object | 否 | HTTP 请求中其他额外的 form data |
timeout | function | 否 | 超时时间,单位为毫秒 |
success | function | 否 | 接口调用成功的回调函数 |
fail | function | 否 | 接口调用失败的回调函数 |
complete | function | 否 | 接口调用结束的回调函数(调用成功、失败都会执行) |
源码文件
wxml文件
<view class="imgBox">
<view><text>车辆照片</text></view>
<view class="imgContant">
<van-uploader accept="image" max-count="1" bind:after-read="afterRead" bind:delete="deleteClick" file-list="{{ fileList }}" />
</view>
</view>
js文件
//获取应用实例
var app = getApp();
Page({
data: {
fileList: [], //图片存放的数组
},
// 删除照片
deleteClick(event) {
var imgData = this.data.fileList;
// 通过splice方法删除图片
imgData.splice(event.detail.index, 1);
// 更新图片数组
this.setData({
fileList: imgData
})
},
// 车辆照片
afterRead(event) {
// loading加载
wx.showLoading({
title: '上传中...'
});
const {file} = event.detail;//获取图片详细信息
let that = this;//防止this指向问题
// 设置请求头,根据项目需求变换
let Authorization = wx.getStorageSync('key')
let headers = {
'content-type': '',
'client_id': 'webApp',
'client_secret': '123456',
}
if (Authorization) {
headers.Authorization = 'Bearer ' + Authorization
}
// 调用wx.uploadFile上传图片方法
wx.uploadFile({
url: "ip" + "url",
method: 'POST',
header: headers,
filePath: file.url,
name: 'file',
formData: {
user: 'test'
},
// 成功回调
success(res) {
// JSON.parse()方法是将JSON格式字符串转换为js对象
var result = JSON.parse(res.data);
// 上传完成需要更新 fileList
const {fileList = []} = that.data;
// 将图片信息添加到fileList数字中
fileList.push({
...file,
url: result.data
});
// 更新存放图片的数组
that.setData({
fileList
});
wx.hideLoading();//停止loading
},
});
},
})
wxss文件
page {
background: #EFF4FF;
}
.imgBox {
font-size: 28rpx;
margin: 3%;
background: white;
padding: 30rpx;
border-radius: 30rpx;
display: flex;
align-items: center;
}
.imgContant {
margin-left: 40rpx;
}
实现效果
进阶 – 封装公共上传、删除方法
上面的实例只是单个的上传,那如果我们遇到几十个需要上传的内容,就要写几十个上传的方法和删除的方法,显然是不太合适的,所以当上传内容比较多时,我们可以将其封装成一个公共的上传、删除方法,通过传递不同的参数去调用这个方法。
wxml文件
<view>
<van-uploader max-count="1" bind:after-read="uploadingsOn" bind:delete="removesOn" data-file-list-key="fileListOne" data-form-key="imgUrlOne" file-list="{{ fileListOne }}" />
</view>
<view>
<van-uploader max-count="3" bind:after-read="uploadingsOn" bind:delete="removesOn" data-file-list-key="fileListTwo" data-form-key="imgUrlTwo" file-list="{{ fileListTwo }}" />
</view>
<button bindtap="submit">提交</button>
js文件
var app = getApp()
Page({
data: {
fileListOne: [], // 第一个文件列表
fileListTwo: [], // 第二个文件列表
form: {
imgUrlOne: [], // 第一个文件列表对应的表单数据
imgUrlTwo: [], // 第二个文件列表对应的表单数据
}
},
// 上传文件
uploadFile(filePath, successCallback, fileListKey, formKey) {
wx.showLoading({
title: '上传中...'
});
wx.uploadFile({
url: app.API_URL + "yourUrl",
method: 'POST',
filePath: filePath,
name: 'file',
success(res) {
var result = JSON.parse(res.data);
successCallback(result, fileListKey, formKey);
wx.hideLoading();
},
});
},
// 删除文件
deleteFile(index, fileList, formKey) {
var imgData = [...fileList];
imgData.splice(index, 1);
var form = {
...this.data.form
};
form[formKey].splice(index, 1); // 删除对应表单数据
return {
fileList: imgData,
form: form
};
},
// 统一删除文件事件处理函数
removesOn(event) {
const index = event.detail.index;
const fileListKey = event.currentTarget.dataset.fileListKey;
const formKey = event.currentTarget.dataset.formKey;
const {
fileList,
form
} = this.deleteFile(index, this.data[fileListKey], formKey);
this.setData({
[fileListKey]: fileList,
form: form
});
},
// 统一上传文件事件处理函数
uploadingsOn(event) {
let that = this;
if (that.beforeRead(event)) {
const {
file
} = event.detail;
const fileListKey = event.currentTarget.dataset.fileListKey;
const formKey = event.currentTarget.dataset.formKey;
this.uploadFile(file.url, function (result, fileListKey, formKey) {
const fileList = that.data[fileListKey];
fileList.push({
...file,
});
const form = that.data.form;
form[formKey].push(app.FILE_URL + result.map.path); // 添加上传后的地址到表单数据
that.setData({
[fileListKey]: fileList,
form: form
});
wx.hideLoading();
}, fileListKey, formKey);
}
},
// 校验图片格式
beforeRead(file) {
if (!/(jpg|jpeg|png|JPG|PNG)/i.test(file.detail.file.url)) {
wx.showToast({
title: '请上传正确格式的图片',
icon: 'none',
})
return false
}
return true
},
// 提交表单
submit() {
// 数组的形式
console.log(this.data.form);
console.log(this.data.fileListOne, this.data.fileListTwo);
// // 将数组转换为逗号分隔的字符串
// const form = { ...this.data.form };
// form.imgUrlOne = form.imgUrlOne.join(",");
// form.imgUrlTwo = form.imgUrlTwo.join(",");
// console.log(form);
},
})
拓展1 – 压缩图片
当涉及到图片的上传时,图片压缩是一个非常重要的话题。随着手机摄像头和相机的不断进步,我们能够拍摄到更高分辨率的照片,但同时也面临着更大的图片文件大小和传输速度的挑战。过大的图片文件会导致网页加载缓慢,增加用户等待时间,甚至可能耗尽用户的流量。因此,我们需要一种方法优化压缩图片的大小。『点此查看官方文档』
utils/imageUtils.js
文件
// 图片压缩方法
function compressImage(filePath) {
return new Promise((resolve, reject) => {
wx.getFileSystemManager().getFileInfo({
filePath,
success(res) {
const fileSize = res.size / 1024 / 1024; // 文件大小,单位MB
if (fileSize > 10) {
console.log(fileSize,"文件大于10MB,需要进行压缩");
// 如果文件大于10MB,需要进行压缩
wx.compressImage({
src: filePath,
quality: 20, // 压缩质量
success(res) {
resolve(res.tempFilePath);
},
fail(err) {
reject(err);
},
});
} else {
// 如果文件小于等于10MB,直接返回原文件路径
resolve(filePath);
}
},
fail(err) {
reject(err);
},
});
});
}
module.exports = {
compressImage,
};
app.js
文件
const imageUtils = require('./utils/imageUtils');//图片压缩
App({
imageUtils,
onLaunch: function () {},
globalData: {
userInfo: null,
},
});
任意文件使用
var app = getApp()
// 上传文件
uploadFile(filePath, successCallback, fileListKey, formKey) {
wx.showLoading({
title: '上传中...'
});
app.imageUtils.compressImage(filePath).then((compressedFilePath) => {
wx.uploadFile({
url: app.API_URL + "yourUrl",
method: 'POST',
filePath: compressedFilePath,
name: 'file',
success(res) {
var result = JSON.parse(res.data);
successCallback(result, fileListKey, formKey);
wx.hideLoading();
},
});
})
},
拓展2 – 回显缓存图片
使用场景:用户填写表单到一半时,因为操作不当或者其它原因退出表单,当用户再次进入表单,需要回显用户上一次填写表单的内容。
Page({
data: {
idCardImg: [], // 存储身份证图片数据的数组
frontImg: [], // 存储正面照片数据的数组
tailImg: [], // 存储背面照片数据的数组
},
onLoad() {
// 在页面加载时,检查本地存储是否存在特定数据,并进行回显
const keys = ['idCardImg', 'frontImg', 'tailImg'];
keys.forEach(key => this.setIfStorageExists(key));
},
// 图片回显方法
setIfStorageExists(key) {
const storageData = wx.getStorageSync(key); // 从本地存储中获取指定键的数据
if (storageData) {
this.setData({
[key]: storageData // 将获取到的数据设置到对应的数据属性中
});
}
},
})
图片缓存代码逻辑
// 统一删除文件事件处理函数
removesOn(event) {
// ... 之前代码不变
// 删除对应的浏览器存储
wx.setStorageSync(fileListKey, fileList);
},
// 统一上传文件事件处理函数
uploadingsOn(event) {
if (that.beforeRead(event)) {
// ... 之前代码不变
// 删除对应的浏览器存储
// 图片缓存
wx.setStorageSync(fileListKey, fileList);
wx.hideLoading();
}, fileListKey, formKey);
}
},
相关推荐
⭐ element表格上传图片必看:如何避免全行上传?
⭐ vue开发者必看!基于element实现文件上传功能的完整教程
⭐ 让图片上传变得更简单:vue和vant的完美融合