Using GraphQL API
Note: Please review the documentation for API 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:
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:
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:
@UIApplicationMainclass 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:
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.