一、实现原理
- wx.showActionSheet():显示操作菜单,选择是从相册选择还是相机拍摄照片
- wx.chooseImage():从本地相册选择图片或使用相机拍照。
- wx.uploadFile():将本地资源上传到服务器。客户端发起一个 HTTPS POST 请求,其中 content-type 为 multipart/form-data。
- wx.previewMedia(): 预览图片和视频。
二、代码
upload.wxml
<view class="study-title">图片上传原理</view>
<view class="show-img-box"><view class="img-item-box" wx:for="{{imgList}}" wx:key="*this" data-src="{{item}}" data-src-list="{{imgList}}" bindtap="clickImg"><image class="img-item" src="{{item}}" /></view><view class="upload" bindtap="chooseImgType"><view class="img-upload"></view></view>
</view>
upload.wxss
/* pages/upload/upload.wxss */
.study-title {width: 100vw;margin: 50rpx 0;font-size: 40rpx;font-weight: 800;text-align: center;
}
.show-img-box {width: 600rpx;display: flex;flex-wrap: wrap;margin: 0 auto;
}.img-item-box {width: 184rpx;height: 184rpx;margin: 4px;background-color: #ccc;
}.img-item {width: 184rpx;height: 184rpx;
}
.upload {margin: 4px;width: 184rpx;height: 184rpx;background: rgba(203, 224, 208, 0.5);border-radius: 5rpx;display: flex;align-items: center;justify-content: center;
}
.img-upload {width: 120rpx;height: 120rpx;background-image: url(https://pro-core.babycdn.com/2021/aosmith/lottery/images2020/watersystem/case/robot/img_upload.png);background-repeat: no-repeat;background-size: cover;
}
upload.js
// pages/upload/upload.js
Page({/*** 页面的初始数据*/data: {imgList: [], // 由于没有可用的服务器域名,因此定义此数据用于展示上传的图片,以演示图片预览功能imgFilePaths: [], // 上传的图片存放路径,有可用的服务器域名用此数据渲染showSelect: false, // 是否显示选择框host: "https://5blog.com/Api", // 服务器域名,此处为错误域名},// 弹出操作菜单,选择获取图片的方式chooseImgType() {// 显示操作菜单wx.showActionSheet({itemList: ["从相册选择", "拍照"],success: (res) => {if (res.tapIndex == 0) {this.chooseImg("album");} else if (res.tapIndex == 1) {this.chooseImg("camera");}},});},// 选择图片chooseImg(type) {let { imgFilePaths } = this.data;wx.chooseImage({// 从本地相册选择照片或使用相机拍照count: 9, // 最多可以选择的图片张数, 默认9sizeType: ["original", "compressed"], // 所选图片的尺寸,默认原图和压缩图都可以sourceType: [type], // 选择图片的来源,默认相册和相机都可以success: async (res) => {// 接口调用成功的回调// console.log("res", res);// res.tempFilePaths是临时文件路径数组,数组内的元素可以直接作为src使用const tempFilePaths = res.tempFilePaths;this.setData({imgList: res.tempFilePaths,});let tempLength = 9 - imgFilePaths.length;let tempFilePaths_ = tempFilePaths.splice(0, tempLength);// 得到所有上传成功后的图片url组成的数组let imgUrlArr = await Promise.all(// 实现上传所有图片到服务器tempFilePaths_.map((item, index) => {// 返回每张图片的上传结果return this.updateImg(item, index);}));console.log("imgUrlArr", imgUrlArr);// 根据需求补充其他内容},fail: (err) => {console.log(type);// 接口调用失败的回调console.log("图片选取上传错误", err);},complete: () => {// 接口调用结束的回调(调用成功、失败都会执行)},});},// 实现将单张图片上传服务器,上传成功返回图片url,上传失败返回falseupdateImg(src, index = 0) {wx.showLoading({title: "上传中...",mask: true,});// 将本地资源上传到服务器接口,客户端发起一个post请求// 其中content-type为multipart/form-datareturn new Promise((resolve, reject) => {wx.uploadFile({url: this.data.host + "/Attach/Index/upload", // 开发者服务器地址filePath: src, // 要上传文件资源的路径(本地路径)header: {"content-type": "multipart/form-data", // 默认值},name: "img", // 文件对应的key,开发者在服务端通过这个key获取文件的二进制内容formData: {// http请求中其他额外的form datatype: "image",index: index,},// 上传成功的回调success: function (res) {console.log("res", res);if (res && res.data && !res.data.error) {let img = JSON.parse(res.data);resolve(img.data);} else {wx.showToast({title: "图片提交失败",icon: "none",duration: 1500,});resolve(false);}},complete: function (res) {wx.hideLoading();},});});},// 实现图片预览clickImg(e) {let src = e.currentTarget.dataset.src;let sources = e.currentTarget.dataset.srcList;console.log(sources);sources = sources.map((item) => {return {url: item, // 链接type: "image", // 默认类型是图片};});// 预览图片和视频接口wx.previewMedia({sources: sources,});},
});
三、效果演示
这里进行了真机调试以演示以上代码的实际运行效果。
此处选择了从相册选择