Vydia/react-native-background-upload

Failed to upload file directly to S3

thangnt-savvy opened this issue · 4 comments

I tried to upload a file directly to S3, but my order of parameters is not as required. Seem I can't change the order of my request.

Here is my code

  const options: any = {
    url: url,
    path: path,
    method: 'POST',
    type: 'multipart',
    field: 'file',
    maxRetries: 2, // set retry count (Android only). Default 2
    headers: {
      'content-type': fileInfo.mimeType, // server requires a content-type header
      'content-length': `${fileInfo.size}`,
    },
    parameters: {
      key: `${fields.key}/${fileInfo.name}`,
      acl: fields['acl'],
      bucket: fields['bucket'],
      'X-Amz-Algorithm': fields['X-Amz-Algorithm'],
      'X-Amz-Credential': fields['X-Amz-Credential'],
      'X-Amz-Date': fields['X-Amz-Date'],
      'X-Amz-Signature': fields['X-Amz-Signature'],
      Policy: fields['Policy'],
      'Content-Type': fileInfo.mimeType,
    },
    notification: {
      enabled: true,
    },
    useUtf8Charset: true,
  };

  Upload.startUpload(options)
    .then(uploadId => {
      console.log('Upload started');
      Upload.addListener('progress', uploadId, data => {
        console.log(`Progress: ${data.progress}%`);
      });
      Upload.addListener('error', uploadId, data => {
        console.log(`Error: ${data.error}%`);
      });
      Upload.addListener('cancelled', uploadId, data => {
        console.log('Cancelled!', data);
      });
      Upload.addListener('completed', uploadId, data => {
        // data includes responseCode: number and responseBody: Object
        console.log('Completed!', data);
      });
    })
    .catch(err => {
      console.log('Upload error!', err);
    });

and S3 error message
Key should be the first item instead of file

<?xml version="1.0" encoding="UTF-8"?>
<Error>
  <Code>InvalidArgument</Code>
  <Message>Bucket POST must contain a field named 'key'.  If it is specified, please check the order of the fields.</Message>
  <ArgumentName>key</ArgumentName>
  <ArgumentValue></ArgumentValue>
</Error>

Hi there,
we got to work with pre-signed URLs.
The change needed is to send it with PUT and type 'raw'.

@anyb1s right I also using pre-signed URL with some configurations but it only seems like work in simulators any ideas why is not working on the real devices

Hi there,
we got to work with pre-signed URLs.
The change needed is to send it with PUT and type 'raw'.

Hi,
I am having the same problem. @anyb1s ,
if I use type 'raw' I get an error that I cannot pass extra parameters:
Error: Parameters supported only in multipart type

How did you make it work on your side? I need to send the parameters that contain the amazon policies and so on to make the pre-signed URL work.
Thanks!

What we do is the following we have an endpoint to presign
`$command = $adapter->getClient()->getCommand('putObject', array_filter([
'Bucket' => $adapter->getBucket(),
'Key' => $path,
'ACL' => 'public-read',
'ContentType' => $request->get('type'),
'Metadata' => [
'content-type' => $request->get('type'),
]
]));

    $signedRequest = $adapter->getClient()->createPresignedRequest($command, '+5 minutes');

    return response()->json([
        'method' => $signedRequest->getMethod(),
        'url' => (string)$signedRequest->getUri(),
        'fields' => [],
        'path' => 'tmp/' . $filename,
        'headers' => [
            'content-type' => $request->get('type'),
        ],
    ]);`

const options = { url: presignResponse.url, path: imagePath, method: presignResponse.method, type: 'raw', field: 'file', maxRetries: 2, // set retry count (Android only). Default 2 headers: { 'content-type': mimeType, // Customize content-type accept: 'application/json', // Customize content-type }, // Below are options only supported on Android notification: { enabled: true, autoclear: true, onProgressTitle: 'Uploading...', onCompleteTitle: 'Upload finished', }, useUtf8Charset: true, };