aws-amplify / amplify-ui

Amplify UI is a collection of accessible, themeable, performant React (and more!) components that can connect directly to the cloud.
https://ui.docs.amplify.aws
Apache License 2.0
913 stars 295 forks source link

Bug (Storage/FileUploader): FileUploader does not upload processed file contents in certain scenarios #6049

Closed choyky closed 2 days ago

choyky commented 2 weeks ago

Before creating a new issue, please confirm:

On which framework/platform are you having an issue?

React

Which UI component?

Storage

How is your app built?

Vite

What browsers are you seeing the problem on?

Firefox

Which region are you seeing the problem in?

No response

Please describe your bug.

FileUploader does not upload modified file content as described in documentation.

For example, in the following code snippet, file content is replaced entirely but FileUploader still uploads the original input file.

const processFile: FileUploaderProps['processFile'] = async ({ file }) => {
  const fileExtension = file.name.split('.').pop();

  const text = "This is the content of my file";
  const blob = new Blob([text], { type: "text/plain" });
  const processedFile = new File([blob], `${file.name}.txt`, { type: "text/plain" });

  return processedFile
    .arrayBuffer()
    .then((filebuffer) => window.crypto.subtle.digest('SHA-1', filebuffer))
    .then((hashBuffer) => {
      const hashArray = Array.from(new Uint8Array(hashBuffer));
      const hashHex = hashArray
        .map((a) => a.toString(16).padStart(2, '0'))
        .join('');
      return { file: processedFile, key: `${hashHex}.txt` };
    });
};

export function FileUploaderExample() {
  return (
    <FileUploader
      acceptedFileTypes={['image/*']}
      path={({ identityId }) => `private/${identityId}/`}
      maxFileCount={3}
      showThumbnails={true}
      processFile={processFile}
    />
  );
}

If the now deprecated accessLevel is used instead of path as below, then the processed file content will be uploaded as expected.

<FileUploader
      acceptedFileTypes={['image/*']}
      accessLevel='private'
      maxFileCount={3}
      showThumbnails={true}
      processFile={processFile}
    />

What's the expected behaviour?

FileUploader uploads processed/modified file contents instead of the original input.

Help us reproduce the bug!

You could use above example code to reproduce the bug. Check the file contents on S3 and verify that it is the same as original input.

Code Snippet

See above.

Console log output

No response

Additional information and screenshots

No response

choyky commented 2 weeks ago

Proposed fix for the issue is submitted here: https://github.com/aws-amplify/amplify-ui/pull/6050

hbuchel commented 2 weeks ago

Hi @choyky thanks for filing this bug and for the proposed solution! I was able to replicate your bug in the latest version. I will bring up your PR with the team.

markd-cmn commented 1 week ago

I've found that the suggested workaround using the legacy accessLevel field does indeed allow the modified File object to be uploaded. However, the key is set to the base file name in that case and path cannot be modified via identityId, so it does not completely address the issue.

dindjarinjs commented 2 days ago

Fix has been deployed @aws-amplify/ui-react-storage@3.4.1