React Native 中的上传

最近做了上传图片到服务端,其实不用第三方模块。
窝建议直接和 web 端一样采用 multipart/form-data 来上传,这样 APP 端和 web 端用的接口可以通用,至于将图片编码成 base64,再到服务端解码保存也是可以的,且效率差别也不是很大。但是由于要改服务端的逻辑,我就懒得用这个方法了。

如果仅从应用层观察,base64 是会按 4/3 比例增加传输成本。
但实际操作上,物理层和 MAC 层协议本身是有做压缩和冗余,所以用 base64,至少在这两层上讲,传输成本并不会按照 4/3 比例增多,传输效率可能和纯二进制序列传输没什么区别。

单文件

let formData = new FormData();

let params = {
  uploadImg: {
    uri: uri,
    type: 'application/octet-stream',
    name: 'image.jpg'
  }
};

for (let key in params) {
  formData.append(key, params[key]);
}

fetch('https://api.domain.com/upload.json', {
  body: formData,
  method: 'post',
  headers: {
    'Auth-Token': 'XXXXX'//php端直接用$_SERVER['HTTP_AUTH_TOKEN]接收
  }
}).then((response) => {
  console.log(response);
});

文件数组

PHP 可以直接用文件数组批量上传文件

<input type="file" name="image[]" />
<input type="file" name="image[]" />
<input type="file" name="image[]" />
<input type="file" name="image[]" />
<input type="file" name="image[]" />

然而我尝试在 RN 中也构造类似的结构却不行:

let params = {
  'uploadImg[]': {
    uri: uri,
    type: 'application/octet-stream',
    name: 'image.jpg'
  },
  'uploadImg[]': {
    uri: uri,
    type: 'application/octet-stream',
    name: 'image.jpg'
  }
};

于是按照 java web 里的类似方式构造是可以的:

let params = {
  'uploadImg[0]': {
    uri: uri,
    type: 'application/octet-stream',
    name: 'image.jpg'
  },
  'uploadImg[1]': {
    uri: uri,
    type: 'application/octet-stream',
    name: 'image.jpg'
  }
};

嫌麻烦的话使用 for 循环构造一下即可

最后总结一下 RN 中有关图片的第三方包 (也是踩坑过程中碰到的 (。・ω・。))

  • react-native-image-picker 图片选取组件,但是不支持多选,裁剪功能不完善,窝现在只用到了它的照相功能,选取需要结合 react-native-image-crop-picker
  • react-native-image-crop-picker 和上面的类似,但是它支持多选和裁剪,然而不支持照相,所以…
  • react-native-image-resizer 这个主要用来压缩图片,一般 iOS 和 Android 拍摄出来的图片都有 3~5MB 左右,所以上传前压缩下当然是极好的