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

upload from file in AWS Amplify Gen 2 #13628

Closed
Jamalseder7008 opened this issue Jul 23, 2024 · 7 comments
Closed

upload from file in AWS Amplify Gen 2 #13628

Jamalseder7008 opened this issue Jul 23, 2024 · 7 comments
Assignees
Labels
Gen 2 Issues related to Gen 2 Amplify projects GraphQL Related to GraphQL API issues question General question

Comments

@Jamalseder7008
Copy link

Environment information

System:
  OS: Linux 5.15 Linux Mint 21.3 (Virginia)
  CPU: (16) x64 11th Gen Intel(R) Core(TM) i7-11800H @ 2.30GHz
  Memory: 55.10 GB / 62.52 GB
  Shell: /bin/bash
Binaries:
  Node: 22.4.1 - ~/.nvm/versions/node/v22.4.1/bin/node
  Yarn: 1.22.22 - ~/.nvm/versions/node/v22.4.1/bin/yarn
  npm: 10.8.1 - ~/.nvm/versions/node/v22.4.1/bin/npm
  pnpm: 9.6.0 - ~/.nvm/versions/node/v22.4.1/bin/pnpm
NPM Packages:
  @aws-amplify/backend: 1.0.4
  @aws-amplify/backend-cli: 1.1.1
  aws-amplify: 6.4.2
  aws-cdk: 2.149.0
  aws-cdk-lib: 2.149.0
  typescript: 5.5.3
AWS environment variables:
  AWS_STS_REGIONAL_ENDPOINTS = regional
  AWS_NODEJS_CONNECTION_REUSE_ENABLED = 1
  AWS_SDK_LOAD_CONFIG = 1
No CDK environment variables

Description

Hey while following these steps: https://docs.amplify.aws/react/build-a-backend/storage/upload-files/#upload-from-file

There is an error in this portion:
uploadData({
path: photos/${file.name},
data: file,
})

the error is property 'name' does not exist on type '{ name: string; readonly id: string; owner?: string | null | undefined; readonly createdAt: string; readonly updatedAt: string; }[]'.ts(2339)

is there some way to solve this?

@Jamalseder7008 Jamalseder7008 added the pending-triage Issue is pending triage label Jul 23, 2024
@ykethan
Copy link
Member

ykethan commented Jul 23, 2024

Hey,👋 thanks for raising this! I'm going to transfer this over to our JS repository for better assistance 🙂

@ykethan ykethan transferred this issue from aws-amplify/amplify-backend Jul 23, 2024
@ykethan ykethan added the Gen 2 Issues related to Gen 2 Amplify projects label Jul 23, 2024
@cwomack cwomack added the Storage Related to Storage components/category label Jul 23, 2024
@cwomack cwomack self-assigned this Jul 23, 2024
@HuiSF
Copy link
Member

HuiSF commented Jul 23, 2024

Hi @ykethan Looking at the error description:

property 'name' does not exist on type '{ name: string; readonly id: string; owner?: string | null | undefined; readonly createdAt: string; readonly updatedAt: string; }[]'.ts(2339)

It seemed to be related to GraphQL APIs instead of the Storage uploadData API, as it mentioned about the model. Could you confirm the source of the error again? Also do you have a model schema that matches the model described in the error?

@Jamalseder7008
Copy link
Author

Jamalseder7008 commented Jul 23, 2024

A small edit, I was actually using a different link to produce this
https://docs.amplify.aws/react/build-a-backend/storage/set-up-storage/
the goal was to setup storage

here is my model scheme:
const schema = a.schema({

//removed todo scheme

File_Model: a.model({
name: a.string().required(),
}).authorization(allow => [allow.owner()]),
});

also my App.tsx is following the same model from the original starter code that Amplify uses for anyone to build a starter app with the modification of each person having their own data after authentication.
const client = generateClient();

//after proper imports
function App() {
const [files, setFile] = useState<Array<Schema["File_Model"]["type"]>>([]);

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

//removed todo functionality code

return (

<Authenticator>

  {({ signOut, user }) => (
    <main>
      <h1>{user?.signInDetails?.loginId}'s files</h1>
      <div>
        <input type="file" onChange={handleChange} />
          <button
            onClick={() =>
              uploadData({
                path: `file-submissions/${files.name}`,
                data: files,
              })
            }
          >
          Upload
        </button>
      </div>
      <button onClick={signOut}>Sign out</button>
    </main>
  )}
</Authenticator>

);
}

export default App;

@cwomack cwomack assigned chrisbonifacio and unassigned cwomack Jul 23, 2024
@cwomack cwomack added GraphQL Related to GraphQL API issues and removed Storage Related to Storage components/category labels Jul 23, 2024
@chrisbonifacio
Copy link
Member

chrisbonifacio commented Jul 29, 2024

Hi @Jamalseder7008, this seems like a TS error rather than an Amplify library issue. From the code shared, it seems you have typed the files state as an array of Files but in the handleChange function you are setting the state to a single file rather than an array of files. You'd need to set the state to an array of files, which you can do by wrapping event.target.files[0] in an array or spreading the current files array and appending it to the end like so:

setFile(prev => [...prev, event.target.files[0])];

Also, in the uploadData function, you are trying to access files.name which will not work because files is an array of files, not a single file. I believe this is where the mentioned error is occurring.
So, you'd have to select a file like files[0].name, making sure you are accessing the correct file.

@chrisbonifacio chrisbonifacio added question General question and removed pending-triage Issue is pending triage labels Jul 29, 2024
@Jamalseder7008
Copy link
Author

Jamalseder7008 commented Jul 30, 2024

Okay, first, thank you for taking the time to try to help me with this. I am still trying to be persistent in solving it, perhaps it is clear but I need a little more help.

I've updated my code to reflect exactly what is being shown in the link in the previous message I sent. I've taken your advice, @chrisbonifacio , about the "files" possibly being an array and that might be causing the problem so I've changed it back into the "file" object.

The errors that the code is giving me is two different errors,

first in line 28:
path: picture-submissions/${file.name},
'file' is possibly 'undefined'.

second in line 29:
data: file,
no overload matches this call

I've uploaded my revised code so that if you'd like to make sure that I'm not making any extra mistakes that could be causing the problem.

I've tried using other advice that essentially get rid of the error about file being possibly null but I believe the answer is simpler than some of the solutions I've seen.
https://stackoverflow.com/questions/61573872/typescript-object-is-possibly-null-when-getting-files-from-event

import { Authenticator } from "@aws-amplify/ui-react";
import '@aws-amplify/ui-react/styles.css'
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 (

    <Authenticator>

      {({ signOut, user }) => (

        <main>
          <h1>{user?.signInDetails?.loginId}'s files</h1>

          <div>
            <input type="file" onChange={handleChange} />

              <button
                onClick={() =>
                  uploadData({
                    path: `picture-submissions/${file.name}`,
                    data: file,
                })
              }
            >
              Upload
            </button>

          </div>

          <button onClick={signOut}>Sign out</button>

        </main>
      )}

    </Authenticator>
  );
}

export default App;

@chrisbonifacio
Copy link
Member

chrisbonifacio commented Jul 30, 2024

Hi @Jamalseder7008, the first error is because name might not be accessible on the file state because state is undefined by default and there's no guarantee that it will be defined by the time the button is clicked to upload. So, it seems you just have to handle the case where the file might be undefined.

Here's an edited version of your code to address the errors:

import { Authenticator } from "@aws-amplify/ui-react";
import "@aws-amplify/ui-react/styles.css";
import React from "react";
import { uploadData } from "aws-amplify/storage";

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

  const handleChange = (event: React.ChangeEvent<HTMLInputElement>) => {
    if (!event.target.files) return; // or handle as an error

    setFile(event.target.files[0]);
  };

  return (
    <Authenticator>
      {({ signOut, user }) => (
        <main>
          <h1>{user?.signInDetails?.loginId}'s files</h1>

          <div>
            <input type="file" onChange={handleChange} />

            <button
              onClick={() => {
                if (!file) return;
                uploadData({
                  path: `picture-submissions/${file.name}`,
                  data: file,
                });
              }}
            >
              Upload
            </button>
          </div>

          <button onClick={signOut}>Sign out</button>
        </main>
      )}
    </Authenticator>
  );
}

export default App;

After handling the possible undefined state, the overload error also seemed to be resolved.

@Jamalseder7008
Copy link
Author

Thank you so much for this help, your advice solved the issue that was occurring. All that had to be adjusted was making sure that the code handled the possibility of file being undefined.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Gen 2 Issues related to Gen 2 Amplify projects GraphQL Related to GraphQL API issues question General question
Projects
None yet
Development

No branches or pull requests

5 participants