项目实践 | 拍照裁剪和图片上传

344 阅读2分钟

APP 端

拍照 ---> 裁剪

1、点击按钮,拍照/选图,调 takePhoto

2、获取所选图的临时路径数组 tempFilePaths

3、将图片保存到本地,得到本地路径 savedFilePath

4、跳转到裁剪页,并将本地路径传递过去

takePhoto() {
  var _this = this;
  //1. 选图 or 拍图
  uni.chooseImage({
    count: 1,  //相册最多选几张,默认9
    sizeType: ['original', 'compressed'], //原图/压缩图,默认二者都有
    sourceType: ['album','camera'],       //相册选择/拍照,默认二者都有
    success: function (res) {
      // 2. 选中图片的临时文件路径数组
      let tempFilePath = res.tempFilePaths[0];
      _this.imageSrc = tempFilePath
      // 3. 图片保存到本地,变成本地路径
      uni.saveFile({
        tempFilePath: tempFilePath,
        success: function (res) {
          var savedFilePath = res.savedFilePath;
          // 4. 跳转到裁剪页,并将本地路径传递过去 
          uni.navigateTo({
            url: '/pages/photo-cropper/photo-cropper?data=' + encodeURIComponent(JSON.stringify(savedFilePath)),
          });
        }
      });
    },
    fail: function(error) {
      console.log('读取文件失败', error);
    }
  })
}	

裁剪 ---> Base64编码

裁剪组件使用了一个插件:ext.dcloud.net.cn/plugin?id=3…

组件的输入是 inputUrl,是从拍照页传递过来的

onLoad(query) {
    // 从拍照页传递过来的临时路径
    const data = JSON.parse(decodeURIComponent(query.data));
    this.inputUrl = data;
}

裁剪完成后会调用 uploadPhoto,将输出路径 outputUrl 转换为 Base64 编码

 // App端的读取文件API
  plus.io.resolveLocalFileSystemURL(upFilePath, function(entry) {
    entry.readFile(function(file) {
      base64Data = file.toLocalURL(); // 转换为本地URL
      // 发送Base64编码的图片数据给服务器
    postImg(base64Data)
    }, function(e) {
      console.error('读取文件失败:' + e.message);
    });
  }, function(e) {
    console.error('解析文件路径失败:' + e.message);
  });

Base64 ---> 图片上传

let postImg = function() {
  uni.request({
    url: 'http://ip:port/router',
    method: 'POST',
    header: {
      'content-type': 'application/json',
    },
    data: {
      img: base64Data,
      //身份验证信息
    },
    success: function(res) {
      //  上传成功后的业务逻辑
    },
    fail: function(error) {
      console.log('图片上传失败', error);
    }
  });
}

小程序端

拍照 ---> 裁剪

上传图片的逻辑和 App 端一致

拍照逻辑

<!-- 相机组件 -->
<camera device-position="back" flash="auto" @error="error" style="">
  <cover-view class="camera-box">
    <cover-view class="scan-text" style="color: #fff;">请将题目放置白色框内</cover-view>
  </cover-view>
</camera>
<!-- 拍照按钮 -->
<image src="@/static/icon/camera.png" 
       @click="takePhoto">
</image>
takePhoto() {
  const ctx = uni.createCameraContext();
  ctx.takePhoto({
    quality: 'high',
    success: (res) => {
      this.src = res.tempImagePath;
      //拍完后跳转到裁剪页并把临时地址传过去
      uni.navigateTo({
        url: '/pages/photo-cropper/photo-cropper?data=' + encodeURIComponent(JSON.stringify(res.tempImagePath)),
      });   
    }
  });
},

裁剪 ---> Base64编码

uni.getFileSystemManager().readFile({
  filePath: upFilePath, 
  encoding: 'base64',
  success: function(fileRes) {
    var base64Data = fileRes.data;
    // 发送Base64编码的图片数据给服务器
    postImg(base64Data)
  })

Base64 ---> 图片上传

同 APP 端