Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

onUploadSuccess not triggered #5800

Open
4 tasks done
nam-truong-le opened this issue Sep 16, 2024 · 19 comments
Open
4 tasks done

onUploadSuccess not triggered #5800

nam-truong-le opened this issue Sep 16, 2024 · 19 comments
Labels
not-reproducible Not able to reproduce the issue pending-community-response Issue is pending response from the issue requestor or other community members pending-response Issue is pending response from the issue requestor question General question

Comments

@nam-truong-le
Copy link

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?

amplify gen2 nextjs template

What browsers are you seeing the problem on?

Chrome

Which region are you seeing the problem in?

Frankfurt

Please describe your bug.

In my app onUploadStart is fired but onUploadSuccess not. Upload succeeds.

What's the expected behaviour?

onUploadSuccess should be fired.

Help us reproduce the bug!

Please check the code snippet.

Code Snippet

  const onUploadStart = useCallback(() => {
    dispatch(setStatus("loading"));
    console.log("uploading");
  }, [dispatch]);

  const onUploadSuccess = useCallback(() => {
    debugger;
    dispatch(setStatus("idle"));
    console.log("uploaded");
  }, [dispatch]);

<FileUploader
            isResumable
            onUploadStart={onUploadStart}
            onUploadSuccess={onUploadSuccess}
            onUploadError={onUploadSuccess}
            maxFileCount={1}
            path={`applicant-photos/${today}/`}
            acceptedFileTypes={["image/*"]}
          />

Console log output

No response

Additional information and screenshots

No response

@github-actions github-actions bot added the pending-triage Issue is pending triage label Sep 16, 2024
@jordanvn
Copy link
Contributor

Hi @nam-truong-le, thanks for submitting this issue. Unfortunately, we have not been able to reproduce this behavior with the FileUploader in a Next.js app. We will need more information to figure out why you're experiencing this.

To confirm, is this the template you're using for your app? https://github.com/aws-samples/amplify-next-template

Additionally, would you be able to share your package.json contents?

@jordanvn jordanvn added question General question pending-response Issue is pending response from the issue requestor and removed pending-triage Issue is pending triage labels Sep 16, 2024
@nam-truong-le
Copy link
Author

Yes, https://github.com/aws-samples/amplify-next-template is the template. My package.json looks like this

{
  "name": "aws-amplify-gen2",
  "version": "0.3.0",
  "private": true,
  "scripts": {
    "dev": "NODE_ENV=development next dev -p 3999",
    "build": "next build",
    "start": "next start",
    "lint": "next lint",
    "format": "prettier --write .",
    "format:check": "prettier --check .",
    "sandbox": "env-cmd -f .env.development ampx sandbox --stream-function-logs --profile vs2 --identifier truong",
    "sandbox:delete": "ampx sandbox delete --profile vs2 --identifier truong"
  },
  "dependencies": {
    "@aws-amplify/adapter-nextjs": "1.2.17",
    "@aws-amplify/ui-react": "6.1.13",
    "@aws-amplify/ui-react-storage": "3.3.2",
    "@emotion/react": "11.13.3",
    "@emotion/styled": "11.13.0",
    "@fontsource/roboto": "5.1.0",
    "@mui/icons-material": "6.1.0",
    "@mui/material": "6.1.0",
    "@mui/material-nextjs": "5.16.6",
    "@mui/types": "7.2.15",
    "@paypal/paypal-js": "8.1.0",
    "@paypal/react-paypal-js": "8.6.0",
    "@reduxjs/toolkit": "2.2.7",
    "@vietnamvisa/vs2-react": "1.6.11",
    "aws-amplify": "6.4.0",
    "crypto-random-string": "5.0.0",
    "dayjs": "1.11.13",
    "lodash.concat": "4.5.0",
    "lodash.difference": "4.5.0",
    "lodash.filter": "4.6.0",
    "lodash.groupby": "4.6.0",
    "lodash.sortby": "4.7.0",
    "lodash.sum": "4.0.2",
    "lodash.sumby": "4.6.0",
    "lodash.truncate": "4.4.2",
    "next": "14.2.11",
    "react": "^18",
    "react-dom": "^18",
    "react-redux": "9.1.2",
    "schema-dts": "1.1.2"
  },
  "devDependencies": {
    "@aws-amplify/backend": "1.2.1",
    "@aws-amplify/backend-cli": "1.2.6",
    "@types/lodash.concat": "4.5.9",
    "@types/lodash.difference": "4.5.9",
    "@types/lodash.filter": "4.6.9",
    "@types/lodash.groupby": "4.6.9",
    "@types/lodash.sortby": "4.7.9",
    "@types/lodash.sum": "4.0.9",
    "@types/lodash.sumby": "4.6.9",
    "@types/lodash.truncate": "4.4.9",
    "@types/node": "20.16.5",
    "@types/react": "18.3.5",
    "@types/react-dom": "18.3.0",
    "ampx": "0.2.1",
    "aws-cdk": "2.158.0",
    "env-cmd": "10.1.0",
    "eslint": "8.57.0",
    "eslint-config-next": "14.2.11",
    "eslint-config-prettier": "8.10.0",
    "prettier": "3.3.3",
    "typescript": "5.6.2"
  },
  "peerDependencies": {
    "react": "^17.0.0 || ^18.0.0",
    "react-dom": "^17.0.0 || ^18.0.0"
  },
  "packageManager": "[email protected]+sha512.73a29afa36a0d092ece5271de5177ecbf8318d454ecd701343131b8ebc0c1a91c487da46ab77c8e596d6acf1461e3594ced4becedf8921b074fbd8653ed7051c"
}

@nam-truong-le
Copy link
Author

If I enable useAccelerateEndpoint, then request fails because of CORS and onUploadError is fired.

@nam-truong-le
Copy link
Author

After some packages are updated, the other issue reported here got resolved #5801

But this issue still persist. This is the updated package.json:

{
  "name": "aws-amplify-gen2",
  "version": "0.3.0",
  "private": true,
  "scripts": {
    "dev": "NODE_ENV=development next dev -p 3999",
    "build": "next build",
    "start": "next start",
    "lint": "next lint",
    "format": "prettier --write .",
    "format:check": "prettier --check .",
    "sandbox": "env-cmd -f .env.development ampx sandbox --stream-function-logs --profile vs2 --identifier truong",
    "sandbox:delete": "ampx sandbox delete --profile vs2 --identifier truong"
  },
  "dependencies": {
    "@aws-amplify/adapter-nextjs": "1.2.18",
    "@aws-amplify/ui-react": "6.3.1",
    "@aws-amplify/ui-react-storage": "3.3.2",
    "@emotion/react": "11.13.3",
    "@emotion/styled": "11.13.0",
    "@fontsource/roboto": "5.1.0",
    "@mui/icons-material": "6.1.0",
    "@mui/material": "6.1.0",
    "@mui/material-nextjs": "6.1.0",
    "@mui/types": "7.2.16",
    "@paypal/paypal-js": "8.1.2",
    "@paypal/react-paypal-js": "8.7.0",
    "@reduxjs/toolkit": "2.2.7",
    "@vietnamvisa/vs2-react": "1.6.11",
    "aws-amplify": "6.6.1",
    "crypto-random-string": "5.0.0",
    "dayjs": "1.11.13",
    "lodash.concat": "4.5.0",
    "lodash.difference": "4.5.0",
    "lodash.filter": "4.6.0",
    "lodash.groupby": "4.6.0",
    "lodash.sortby": "4.7.0",
    "lodash.sum": "4.0.2",
    "lodash.sumby": "4.6.0",
    "lodash.truncate": "4.4.2",
    "next": "14.2.11",
    "react": "^18",
    "react-dom": "^18",
    "react-redux": "9.1.2",
    "schema-dts": "1.1.2"
  },
  "devDependencies": {
    "@aws-amplify/backend": "1.2.1",
    "@aws-amplify/backend-cli": "1.2.6",
    "@types/lodash.concat": "4.5.9",
    "@types/lodash.difference": "4.5.9",
    "@types/lodash.filter": "4.6.9",
    "@types/lodash.groupby": "4.6.9",
    "@types/lodash.sortby": "4.7.9",
    "@types/lodash.sum": "4.0.9",
    "@types/lodash.sumby": "4.6.9",
    "@types/lodash.truncate": "4.4.9",
    "@types/node": "20.16.5",
    "@types/react": "18.3.6",
    "@types/react-dom": "18.3.0",
    "ampx": "0.2.1",
    "aws-cdk": "2.158.0",
    "env-cmd": "10.1.0",
    "eslint": "8.57.1",
    "eslint-config-next": "14.2.11",
    "eslint-config-prettier": "8.10.0",
    "prettier": "3.3.3",
    "typescript": "5.6.2"
  },
  "peerDependencies": {
    "react": "^17.0.0 || ^18.0.0",
    "react-dom": "^17.0.0 || ^18.0.0"
  },
  "packageManager": "[email protected]+sha512.73a29afa36a0d092ece5271de5177ecbf8318d454ecd701343131b8ebc0c1a91c487da46ab77c8e596d6acf1461e3594ced4becedf8921b074fbd8653ed7051c"
}

@nam-truong-le
Copy link
Author

onStart works perfectly but onComplete not.

Bildschirmfoto 2024-09-17 um 10 20 09

@nam-truong-le
Copy link
Author

The utils function uploadFile doesn't resolve so .then(...) isn't triggered:

Bildschirmfoto 2024-09-17 um 10 27 12

@nam-truong-le
Copy link
Author

I went to this file and what I can observe is: this packages/core/src/clients/internal/composeServiceApi.ts is executed twice

  • The first time both line 15 and 19 are executed
  • The second time only line 15
Bildschirmfoto 2024-09-17 um 12 20 21

@esauerbo
Copy link
Contributor

Hey @nam-truong-le thanks for all the detailed information! I tried reproducing this with a simplified version of your package.json (I only included necessary dependencies for FileUploader) and removed the dispatch logic, and onUploadSuccess was triggered.

It's possible this is related to the dispatch logic; can you try simplifying your onUploadSuccess to just include a console.log statement and let us know if that gets triggered?

@nam-truong-le
Copy link
Author

nam-truong-le commented Sep 18, 2024

I switched to this simple callbacks, without dispatch and without useCallback:

  const onUploadStart = () => {
    debugger;
    // dispatch(setStatus("loading"));
    console.log("uploading");
  };

  const onUploadSuccess = () => {
    debugger;
    // dispatch(setStatus("idle"));
    console.log("uploaded");
  };

  const onUploadFailure = () => {
    debugger;
    // dispatch(setStatus("failed"));
  };

          <FileUploader
            onUploadStart={() => onUploadStart()}
            onUploadSuccess={() => onUploadSuccess()}
            onUploadError={() => onUploadFailure()}
            maxFileCount={1}
            path={`applicant-photos/${today}/`}
            acceptedFileTypes={["image/*"]}
          />

But it's still not working.

@nam-truong-le
Copy link
Author

nam-truong-le commented Sep 18, 2024

Now I see that the component uploads the file twice to S3 and then somehow the two parallel processes breaking the whole thing?

@nam-truong-le
Copy link
Author

The reason is this hook executes the upload twice:

Bildschirmfoto 2024-09-18 um 10 10 48

@nam-truong-le
Copy link
Author

Looks like this is called too late:

Bildschirmfoto 2024-09-18 um 10 28 37

If this is called before the second time useUploadFiles is triggered, then file has status "uploading" and then the second upload isn't triggered.

@nam-truong-le
Copy link
Author

nam-truong-le commented Sep 18, 2024

Since onStart is executed asynchronously, it would be better to move the setUploadingFile(...) call to line 84 or after line 108, ensuring the file is immediately marked as "uploading." (I'm referring to this)

Logically, it also makes sense to flag the file as "uploading" as soon as uploadFile is invoked, rather than waiting for the onStart callback. There could be a lot happening between these two events, and if the useEffect function is triggered again during that time, the file might not be marked correctly.

Bildschirmfoto 2024-09-18 um 10 44 58

@nam-truong-le
Copy link
Author

I made this change #5808 locally and tested and it works perfectly.

@esauerbo
Copy link
Contributor

@nam-truong-le thanks for digging into this issue and creating a PR. We'll review as a team and follow up.

In the meantime, I'm still curious why the file is being uploaded twice to S3. Can you provide your backend configuration (your call to defineStorage)?

Additionally, can you try uploading a file without the FileUploader component and see if that results in the same issue? Something like this:

import React from 'react';
import { uploadData } from 'aws-amplify/storage';

function App() {
  const [file, setFile] = React.useState();

  const handleChange = (event: any) => {
    setFile(event.target.files[0]);
  };

  return (
    <div>
      <input type="file" onChange={handleChange} />
        <button
          onClick={async () => {
            try {
              const result = await uploadData({
                path: `applicant-photos/${today}/${file.name}`,
                data: file,
              }).result;
              console.log("Uploaded file: ", result);
            } catch (error) {
              console.error("Error uploading file: ", error);
            }
          }}
        >
        Upload
      </button>
    </div>
  );
}

@nam-truong-le
Copy link
Author

This is my storage config:

import { defineStorage } from "@aws-amplify/backend";

export const storage = defineStorage({
  name: `shopAppStorage-${process.env.AWS_BRANCH}`,
  access: (allow) => ({
    "applicant-photos/*": [allow.guest.to(["write", "read"]), allow.authenticated.to(["write", "read"])],
  }),
});

@nam-truong-le
Copy link
Author

I'm still curious why the file is being uploaded twice to S3

I think it happens because the file gets sent to S3 and marked as "uploading" a bit too late. Before that happens, React triggers the hook again (for some reason I'm not sure of), and at that point, the file still shows as "queued." and it gets sent again.

@nam-truong-le
Copy link
Author

I have to change your code snippet a little bit but it works perfectly without the FileUploader:

  const [file, setFile] = useState<File | null>(null);

  const handleChange = (event: any) => {
    setFile(event.target.files[0]);
  };

<div>
            <input type="file" onChange={handleChange} />
            <button
              onClick={async () => {
                if (!file) {
                  return;
                }
                try {
                  const result = await uploadData({
                    path: `applicant-photos/${today}/${file.name}`,
                    data: file,
                  }).result;
                  console.log("Uploaded file: ", result);
                } catch (error) {
                  console.error("Error uploading file: ", error);
                }
              }}
            >
              Upload
            </button>
          </div>
Bildschirmfoto 2024-09-19 um 06 44 39

@esauerbo esauerbo removed the pending-response Issue is pending response from the issue requestor label Sep 19, 2024
@esauerbo
Copy link
Contributor

@nam-truong-le thanks for the information. Since you're consistently seeing this error, would you be able to provide a minimal reproduction?

This ideally would be a Github repository that contains the minimum amount of code/dependencies that still results in this behavior. Make sure to remove any sensitive information, and let us know if you need further guidance with that. This will help us narrow down the cause and validate potential solutions since we haven't been able to reproduce on our end.

@esauerbo esauerbo added pending-response Issue is pending response from the issue requestor not-reproducible Not able to reproduce the issue labels Sep 19, 2024
@jordanvn jordanvn added the pending-community-response Issue is pending response from the issue requestor or other community members label Sep 19, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
not-reproducible Not able to reproduce the issue pending-community-response Issue is pending response from the issue requestor or other community members pending-response Issue is pending response from the issue requestor question General question
Projects
None yet
Development

No branches or pull requests

3 participants