**Note:** Please review the documentation for [API](/sdk/api/graphql) before you proceed with the rest of this section. You can upload and download Amazon S3 Objects using AWS AppSync, a GraphQL based solution to build data-driven apps with real-time and offline capabilities. Sometimes you might want to create logical objects that have more complex data, such as images or videos, as part of their structure. _For example, you might create a Person type with a profile picture or a Post type that has an associated image_. You can use AWS AppSync to model these as GraphQL types. If any of your mutations have a variable with `bucket`, `key`, `region`, `mimeType`, and `localUri` fields, the SDK uploads the file to S3 for you. Update file `amplify/backend/api/yourAppName/schema.graphql` using the following schema which has a `S3Object` type: ```graphql type Picture @model { id: ID! name: String owner: String visibility: Visibility file: S3Object createdAt: String } type S3Object { bucket: String! region: String! key: String! localUri: String! mimeType: String! } enum Visibility { public private } ``` and run `amplify push` to update the AppSync backend resource, remember to choose `update API.swift` when `Amplify CLI` prompts the choice The AWS AppSync SDK doesn't take a direct dependency on the AWS SDK for S3, but takes in `AWSS3TransferUtility`. You will also need to take a dependency on the `AWSS3` SDK. You can do that by updating your Podfile: ```ruby target: 'PostsApp' do use_frameworks! pod 'AWSAppSync' pod 'AWSS3' end ``` Then run `pod install` to fetch the new dependencies. Update the `class AppDelegate: UIResponder, UIApplicationDelegate` in `AppDelegate.swift` to configure `AWSAppSyncClient` and `AWSS3TransferUtility` like below: ```swift @UIApplicationMain class AppDelegate: UIResponder, UIApplicationDelegate { var appSyncClient: AWSAppSyncClient? func application( _ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? ) -> Bool { // Add the following config code do { let cacheConfiguration = try AWSAppSyncCacheConfiguration() let appSyncServiceConfig = try AWSAppSyncServiceConfig() let appSyncConfig = try AWSAppSyncClientConfiguration( appSyncServiceConfig: appSyncServiceConfig, cacheConfiguration: cacheConfiguration, s3ObjectManager: AWSS3TransferUtility.default()) appSyncClient = try AWSAppSyncClient(appSyncConfig: appSyncConfig) print("AppSync Client Initialized") } catch { print("Error initializing AppSync Client") } return true } } ``` And to automatically upload image when doing the api mutation. You can create the following method to trigger the action: ```swift func uploadImage() { let s3ObjectInput = S3ObjectInput( bucket: "yourBucket", region: "yourBucketRegion", key: "public/imageName.jpeg", localUri: "uriOfImageToUpload", mimeType: "jpeg" ) let pictureMutationInput = CreatePictureInput( id: UUID().uuidString, name: "yourInputName", owner: "yourName", visibility: Visibility(rawValue: "public"), file: s3ObjectInput ) appSyncClient.perform( mutation: CreatePictureMutation(input: pictureMutationInput) ) { (result, error) in if let error = error as? AWSAppSyncClientError { print("Error occurred: \(error.localizedDescription )") } if let resultError = result?.errors { print("Error saving the item on server: \(resultError)") return } } } ``` Note: Remember to replace the `bucket` and `region` with what you find in `awsconfiguration.json` The mutation operation doesn't require any specific changes in method signature. It requires only an `S3Object` with `bucket`, `key`, `region`, `localUri`, and `mimeType`. Now when you do a mutation, it automatically uploads the specified file to Amazon S3 using the `AWSS3TransferUtility` client internally.