amplify-js: S3Object doesn't upload file from client

First, when the docs say:

input CreateTodoInput {
  id: ID
  name: String!
  description: String
  file: S3ObjectInput # This input type will be generated for you
}

I get an error Type "S3ObjectInput" not found in document. and I have to add S3ObjectInput manually.

This is my schema (the docs are not very clear on it so I put it together from similar questions)

type Picture @model {
  id: ID!
  file: S3Object!
  url: String!
  rating: Int
  appearedForRanking: Int
}

type S3Object {
  bucket: String!
  key: String!
  region: String!
}

input CreatePictureInput {
  id: ID
  file: S3ObjectInput!
  url: String!
  rating: Int
  appearedForRanking: Int
}

input S3ObjectInput {
  bucket: String!
  region: String!
  localUri: String
  visibility: Visibility
  key: String
  mimeType: String
}

enum Visibility {
  public
  protected
  private
}

And this is the client code (with React)

class PictureUpload extends Component {

  state = { fileUrl: '', file: '', filename: '' }

  handleChange = e => {
    let file = e.target.files[0]
    let filext = file.name.split('.').pop()
    let filename = uuid() + '.' + filext

    this.setState({
      fileUrl: URL.createObjectURL(file),
      filename: filename
    })
  }

  saveFile = async () => {
    let visibility = 'public'

    let fileObj = {
      bucket: awsConfig.aws_user_files_s3_bucket,
      region: awsConfig.aws_user_files_s3_bucket_region,
      key: visibility + '/' + this.state.filename,
      mimeType:'image/jpeg',
      localUri: this.state.fileUrl,
      visibility: visibility
    }

    try {
      const picture = await API.graphql(
        graphqlOperation(mutations.createPicture, {
          input: {
            url: this.state.filename,
            file: fileObj
          }
        })
      )

The problem is that the mutation runs without errors, setting the DB records, but the file does not appear in S3. The docs say the SDK uploads the file to Amazon S3 for you. so I don’t think I forgot to add something.

Any idea why the upload doesn’t happen?

About this issue

  • Original URL
  • State: closed
  • Created 5 years ago
  • Comments: 15 (7 by maintainers)

Most upvoted comments

@ilyador

I see how this can be confusing, I’ll be sharing this feedback with the team to improve the docs.

To try to clarify a little bit further:

  • AWS Amplify JS
    • This library
  • AWS AppSync
    • The AWS managed GraphQL service with real-time data
  • API category
    • One of the AWS Amplify JS categories. It provides support for REST and GraphQL apis.
  • AWS AppSync SDK

This means that you have two ways to interact with AWS AppSync GraphQL Apis:

  • Using Amplify JS API category
  • Using the aws-appsync sdk

On the TOC we have this structure that kind of mimics what I wrote, but yeah, it can of course be improved

image

Hi @ilyador

I don’t understand the difference. What do you mean by AWS AppSync SDK section?

The Amplify team provides support to interact with GraphQL apis in two packages, the Amplify API category, and the the aws-appsync package.

aws-appsync is a full fledged graphql client for more complex use cases, it is based on the Apollo Client and gives you support for offline-first apps, optimistic UIs, automatic uploading of complex objects, a cache and lots of more features that might be overkill for some scenarios.

For simpler use cases, Amplify is the recommended way to go.

Do you mean I need to use AWSAppSyncClient instead of API.graphql?

The automatic upload of complex objects is a feature of the aws-appsync package. The docs you looked at were probably for this package. You can look at this sample app for usage.

The way that aws-appsync determines if it needs to upload a file, is that it looks for a field with this shape in the mutation:

input S3ObjectInput {
  bucket: String!
  region: String!
  localUri: String
  visibility: Visibility
  key: String
  mimeType: String
}

If you don’t want to use the apollo based client (aws-appsync), you need to upload the file yourself using the Storagecategory. Please note that we have a feature request that we are tracking to add automatic upload in Amplify too #2706

Is there an advantage uploading the file this way and not with Storage?

The advantage is that the sdk uploads the file for you automatically, but you might not want/need all the extra features (and potential increase in bundle size) in your scenario.

Can I use Amplify and the AWSAppSyncClient together in the same client?

Yes! You can take a look at the sample app I mentioned earlier, it uses both. Take a look specifically at https://github.com/aws-samples/aws-amplify-graphql/blob/7b3da9f221c02b1363f8d784863f30bd696ea8e0/src/Components/AddPhoto.js#L36-L67

A few other questions @manueliglesias

In the aws-amplify-graphql sample app the issues are disabled for some reason, so I’ll ask here:

Why are those mutations created inside the app and not part of the auto-generated ones that Amplify CLI builds? https://github.com/aws-samples/aws-amplify-graphql/blob/master/src/Components/AddPhoto.js#L86


When building the app with Amplify CLI, I get the config file generated, yet in the SDK docs it is shown how to build the config manually. Do I need a different config?


I get an error Type "S3ObjectInput" not found in document. and I have to add S3ObjectInput manually.

Is that a bug?

@ilyador

To amend my response from earlier today, what could have we done better in the docs to avoid potential confusions?