skip to Main Content

I’m creating a Web service using AWS S3 in Node, where users upload files that are supposed to have an author metadata tag. When a user uploads, the following kind of pre-signed URL is created to upload the file securely on the client-side, with sensitive values redacted (due to the limitations of my hosting service, full server-side uploading is not an option):

https://my-website.s3.tebi.io/category/subcategory/file_name.wav?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Content-Sha256=UNSIGNED-PAYLOAD&X-Amz-Credential=<redacted>&X-Amz-Date=<redacted>&X-Amz-Expires=900&X-Amz-Signature=<redacted>&X-Amz-SignedHeaders=host&x-amz-meta-author=John%20Doe&x-id=PutObject

Then the file finishes uploading by sending a Fetch request with the above signedURL:

fetch(signedURL, {
    method: 'PUT',
    headers: {
        "Content-Length": new Blob([file]).size
    },
    body: new Blob([file], { type: mimeType })
})
.then(response => {
    if(response.ok) fileUploaded = true;
})
.catch(error => console.error(error));

I can successfully view the uploaded files via ListObjectsV2Command, but when I try to view the metadata via HeadObjectCommand on the object in the bucket, x-amz-meta-author is nowhere to be found (while the other metadata appears exactly as expected, including the file size):

{
  data: {
    '$metadata': {
      httpStatusCode: 200,
      requestId: '<redacted>',
      extendedRequestId: 'node-usw-2',
      cfId: undefined,
      attempts: 1,
      totalRetryDelay: 0
    },
    AcceptRanges: 'bytes',
    LastModified: <redacted>,
    ContentLength: 66528,
    ETag: '"<redacted>"',
    CacheControl: 'no-cache',
    ContentType: 'audio/flac',
    Metadata: {}
  }
}

I have double-checked to make sure x-amz-meta-author is in the ExposedHeader list to avoid CORS issues. Any ideas for what I’m missing? I’m happy to provide additional details as needed. Thanks in advance!

1

Answers


  1. Chosen as BEST ANSWER

    The response from @jarmod was right on the money! Adding x-amz-meta-author to the headers for the PUT request allowed the data to be available in the HeadObjectCommand:

    fetch(signedURL, {
        method: 'PUT',
        headers: {
            "Content-Length": new Blob([file]).size
            "x-amz-meta-author": "John Doe"
        },
        body: new Blob([file], { type: mimeType })
    })
    .then(response => {
        if(response.ok) fileUploaded = true;
    })
    .catch(error => console.error(error));
    
    {
      data: {
        '$metadata': {
          httpStatusCode: 200,
          requestId: '<redacted>',
          extendedRequestId: 'node-usw-2',
          cfId: undefined,
          attempts: 1,
          totalRetryDelay: 0
        },
        AcceptRanges: 'bytes',
        LastModified: <redacted>,
        ContentLength: 66528,
        ETag: '"<redacted>"',
        CacheControl: 'no-cache',
        ContentType: 'audio/flac',
        Metadata: { author: 'John Doe' }
      }
    }
    

Please signup or login to give your own answer.
Back To Top
Search