使用react-native-image-picker和axios将图像上传到S3预签名URL

时间:2020-05-28 15:46:59

标签: reactjs react-native axios react-native-image-picker

我正在尝试使预先签名的url图片上传正常。当前,当从IOS模拟器中选择图像时,上传成功,但是,当我实际尝试查看文件时,似乎文件已损坏并且无法作为图像打开。我怀疑这与我的FormData有关,但不确定。

export async function receiptUpload(file) {

  const date = new Date();
  const headers = await getAWSHeaders();

  const presignUrl = await request.post(
      urls.fileUpload.presignUpload,
      {file_name: `${date.getTime()}.jpg`},
      {headers}
    )
    .then(res => res.data);

  const formData = new FormData();
  formData.append('file', {
    name: `${date.getTime()}.jpg`,
    uri: file.uri,
    type: file.type
  });

  const fileUpload = presignUrl.presignUrl && await request.put(
      presignUrl.presignUrl,
      formData
    )
    .then(res => res.status === 200);

}

我已经尝试通过其他修复方法来更改文件uri,就像这样...

Platform.OS === 'android' ? file.uri : file.uri.replace('file://', '');

但这似乎也不起作用。

2 个答案:

答案 0 :(得分:1)

我最近在当前项目中进行了此操作,以下代码是我的用例的有效示例。即使我正在上传到AWS S3,也不需要转换为Blob,所以如果您正在其他地方上传,则可能是个问题。

export const uploadMedia = async (fileData, s3Data, setUploadProgress = () => {}) => {
    let sendData = { ...fileData };
    sendData.data.type = sendData.type;

    let formData = new FormData();

    formData.append('key', s3Data.s3Key);
    formData.append('Content-Type', fileData.type);
    formData.append('AWSAccessKeyId', s3Data.awsAccessKey);
    formData.append('acl', 'public-read');
    formData.append('policy', s3Data.s3Policy);
    formData.append('signature', s3Data.s3Signature);

    formData.append('file', sendData.data);

    return axios({
        method: 'POST',
        url: `https://${s3Data.s3Bucket}.s3.amazonaws.com/`,
        data: formData,
        onUploadProgress: progressEvent => {
            let percentCompleted = Math.floor((progressEvent.loaded * 100) / progressEvent.total)
            setUploadProgress(percentCompleted);
        }
    })
}

我首先要检查问题出在哪里。上传之后,您可以在尝试将其上传到的任何存储服务上查看它。如果是这样,那是React Native方面的事情。如果它从未上传到该位置,则说明您在上传过程中出错。可以帮助您跟踪错误的确切位置。

答案 1 :(得分:0)

最近我不得不为一个项目这样做。我认为直接来自文件输入的数据是base64字符串。因此,问题在于您只是通过传递数据字段来上传base64字符串而不是图像。在使用以下方法上传到签名的URL之前,我必须对其进行处理。

private dataUriToBlob(dataUri) {
    const binary = atob(dataUri.split(',')[1]);
    const array = [];
    for (let i = 0; i < binary.length; i++) {
        array.push(binary.charCodeAt(i));
    }
    return new Blob([new Uint8Array(array)], { type: 'image/jpeg' });
}