微信原生实现一个简易的图片上传功能

一、实现原理

  1. wx.showActionSheet():显示操作菜单,选择是从相册选择还是相机拍摄照片
  2. wx.chooseImage():从本地相册选择图片或使用相机拍照。
  3. wx.uploadFile():将本地资源上传到服务器。客户端发起一个 HTTPS POST 请求,其中 content-type 为 multipart/form-data。
  4. wx.previewMedia(): 预览图片和视频。

二、代码

upload.wxml

html 复制代码
<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

css 复制代码
/* 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

javascript 复制代码
// 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,
    });
  },
});

三、效果演示

这里进行了真机调试 以演示以上代码的实际运行效果。

此处选择了从相册选择




相关推荐
满怀1015几秒前
【Flask全栈开发指南】从零构建企业级Web应用
前端·python·flask·后端开发·全栈开发
小杨升级打怪中27 分钟前
前端面经-webpack篇--定义、配置、构建流程、 Loader、Tree Shaking、懒加载与预加载、代码分割、 Plugin 机制
前端·webpack·node.js
Yvonne爱编码41 分钟前
CSS- 4.4 固定定位(fixed)& 咖啡售卖官网实例
前端·css·html·状态模式·hbuilder
SuperherRo1 小时前
Web开发-JavaEE应用&SpringBoot栈&SnakeYaml反序列化链&JAR&WAR&构建打包
前端·java-ee·jar·反序列化·war·snakeyaml
大帅不是我1 小时前
Python多进程编程执行任务
java·前端·python
前端怎么个事1 小时前
框架的源码理解——V3中的ref和reactive
前端·javascript·vue.js
Ciito1 小时前
将 Element UI 表格元素导出为 Excel 文件(处理了多级表头和固定列导出的问题)
前端·vue.js·elementui·excel
不爱吃饭爱吃菜2 小时前
uniapp微信小程序一键授权登录
前端·javascript·vue.js·微信小程序·uni-app
heart000_12 小时前
从零开始打造个人主页:HTML/CSS/JS实战教程
javascript·css·html
90后小陈老师3 小时前
3D个人简历网站 5.天空、鸟、飞机
前端·javascript·3d