一、实现原理
- 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, // 最多可以选择的图片张数, 默认9
sizeType: ["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,上传失败返回false
updateImg(src, index = 0) {
wx.showLoading({
title: "上传中...",
mask: true,
});
// 将本地资源上传到服务器接口,客户端发起一个post请求
// 其中content-type为multipart/form-data
return 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 data
type: "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,
});
},
});
三、效果演示
这里进行了真机调试以演示以上代码的实际运行效果。
此处选择了从相册选择