Docs
Launch GraphOS Studio

File uploads

Enabling file uploads in Apollo Client for iOS


supports file uploads via the GraphQL multipart request specification with a few caveats:

  • Uploading files with is most often suitable for proof-of-concept applications. In production, using purpose-built tools for file uploads may be preferable. Refer to this blog post for the advantages and disadvantages of multiple approaches.
  • The Apollo Router doesn't support multipart/form-data uploads.

Uploading files with Apollo iOS

Apollo iOS only supports uploads for a single , not for batch operations. You can upload multiple files with a single operation if your server supports it, though.

To upload a file, you need:

  • A NetworkTransport which also supports the UploadingNetworkTransport protocol on your ApolloClient instance. If you're using RequestChainNetworkTransport (which is set up by default), this protocol is already supported.
  • The correct MIME type for the data you're uploading. The default value is application/octet-stream.
  • Either the data or the file URL of the data you want to upload.
  • A which takes an Upload as a parameter. Note that this must be supported by your server.

Here is an example of a GraphQL for a mutation that accepts a single upload, and then returns the id for that upload:

mutation UploadFile($file:Upload!) {
singleUpload(file:$file) {
id
}
}

If you want to use this to upload a file called a.txt, it looks something like this:

// Create the file to upload
guard let fileURL = Bundle.main.url(forResource: "a", withExtension: "txt"),
let file = GraphQLFile(
fieldName: "file", // Must be the name of the field the file is being uploaded to
originalName: "a.txt",
mimeType: "text/plain", // <-defaults to "application/octet-stream"
fileURL: fileURL
) else {
// Either the file URL couldn't be created or the file couldn't be created.
return
}
// Actually upload the file
client.upload(
operation: UploadFileMutation(file: "a"), // <-- `Upload` is a custom scalar that's a `String` under the hood.
files: [file]
) { result in
switch result {
case .success(let graphQLResult):
print("ID: \(graphQLResult.data?.singleUpload.id)")
case .failure(let error):
print("error: \(error)")
}
}

A few other notes:

  • Due to some limitations around the spec, whatever the file is being added for should be at the root of your GraphQL query. So if you have something like:

    mutation AvatarUpload($userID: GraphQLID!, $file: Upload!) {
    id
    }

    it will work, but if you have some kind of object encompassing both of those like this:

    # Assumes AvatarObject(userID: GraphQLID, file: Upload) exists
    mutation AvatarUpload($avatarObject: AvatarObject!) {
    id
    }

    it will not. Generally you should be able to deconstruct upload objects to allow you to send the appropriate fields.

  • If you are uploading an array of files, you need to use the same name for each file. These will be updated at send time.

  • If you are uploading an array of files, the array of Strings passed into the query must be the same number as the array of files.

Previous
Including Apollo as an XCFramework
Next
Request Chain Customization
Edit on GitHubEditForumsDiscord

© 2024 Apollo Graph Inc.

Privacy Policy

Company