I'm adding support for uploading files within the client. Is there any interest in a PR to add it into the project?
Since the GraphQL spec does not mention file uploads, I'm considering just adding another function to the client that accepts [String: GraphQLFile] with GraphQLFile having the mime type/file data.
Any other suggestions are welcome.
Support for file uploads would be great, so definitely interested in a PR! We may want to coordinate with related efforts in the Apollo JavaScript client and server however, see here.
I would suggest following the graphql-upload and apollo-upload-client strategy using multipart forms. This approach is making its way into the core.
You can see the structure for standard and batched multipart GraphQL requests here. A single GraphQL server will be able to handle uploads from all clients the same way if they follow this pattern.
Edit: The final GraphQL multipart request spec: https://github.com/jaydenseric/graphql-multipart-request-spec
@jaydenseric Thanks for the link. Given what you guys are working on now my implementation might be too basic. My goal was to add the functionality of adding files (provide perform() with a list of files) and allow the caller to update the mutation manually.
So given the GraphQL example you used here:
let imageData: Data = ...
let pdfData: Data = ...
// GraphQLFile would be a class in apollo-ios
let files = [GraphQLFile(fieldName: "files.0", originalName: "test-file-1.png", mimeType: "image/png", "data": imageData), GraphQLFile(fieldName: "files.1", originalName: "test-file-2.pdf", mimeType: "application/pdf", "data": pdfData)]
// Here we can format the upload however we want
let mutation = MultipleUploadMutation(files: files.map({Upload(name: $0.originalName, type: $0.mimeType, size: $0.count)}))
let client = ApolloClient( ... )
client.perform(mutation: mutation, files: files)
This allows the apollo-ios to support multipart uploads while also not forcing a specific spec.
The HTTPNetworkTransport class would check to see if there are any files (files is optional and defaults to nil). If there are files, then it would create a multipart request instead.
We still don't have support for multipart upload via apollo-ios?
Would love to see this added
Please take a look at #626 if you're interested in this feature and let us know if there's anything there which is missing!
@designatednerd In our API we are using the Upload type-alias as an attribute in the mutation. So for example when updating a profile, we can pass the image file in the mutation as one of the parameters so we can update the profile image and the rest of the info in one step. Unfortunately, on our iOS client we cannot use it because Apollo doesn't support this Upload type for now.
Is it possible to have also this functionality implemented?
@victormihaita I'd certainly take a look at a PR implementing that addition, but as far as I can tell, it's not part of the final multi-part request spec, which is what we're adding support for with #626.
@designatednerd I know is not. Is just a topic related to this PR and I thought it would be the best place to mention it :)
Fair enough - I think one thing to be aware of in terms of a PR is looking at how this functionality is handled on other clients - not just for iOS but other GraphQL clients, especially in the absence of a spec for stuff like this. We can discuss further on Spectrum if you'd like!
Uploads conforming to the multi-part request spec have shipped with 0.13.0 - if you have further needs, please open a new issue or even better, open a PR 馃槃
I know this is closed but +1... really need the Upload type to be supported in ios!
@emmya it should already be supported! 馃殌馃殌
https://www.apollographql.com/docs/ios/mutations/#uploading-files
@emmya Yes ^ that is the solution!
@jaydenseric Thanks for the link. Given what you guys are working on now my implementation might be too basic. My goal was to add the functionality of adding files (provide
perform()with a list of files) and allow the caller to update the mutation manually.So given the GraphQL example you used here:
let imageData: Data = ... let pdfData: Data = ... // GraphQLFile would be a class in apollo-ios let files = [GraphQLFile(fieldName: "files.0", originalName: "test-file-1.png", mimeType: "image/png", "data": imageData), GraphQLFile(fieldName: "files.1", originalName: "test-file-2.pdf", mimeType: "application/pdf", "data": pdfData)] // Here we can format the upload however we want let mutation = MultipleUploadMutation(files: files.map({Upload(name: $0.originalName, type: $0.mimeType, size: $0.count)})) let client = ApolloClient( ... ) client.perform(mutation: mutation, files: files)This allows the apollo-ios to support multipart uploads while also not forcing a specific spec.
The
HTTPNetworkTransportclass would check to see if there are anyfiles(filesis optional and defaults tonil). If there are files, then it would create a multipart request instead.
how to upload single file using iOS Client
mutation uploadFile($file:Upload!,$business_id:String!){
uploadFile(file: $file,business_id: $business_id)
}
this is my mutation how to call this mutation
Hey guys,
Our server has a pretty basic upload file mutation that works great with our web client:

When my ios dev generates the apollo graphql API on his end using the server-side schema, it converts the Upload type to a String.
He then follows the documentation but what gets received by the server is.... a string.
I'll have him elaborate here but this is blocking us currently. Is tehre something I need to do special on the server-side to support ios? We are at a loss, any help is appreciated. Thank you!
In regards to what @emmya mentioned above. This is what I am doing on my end to perform the upload on iOS...
if let imageData = profileImage?.jpegData(compressionQuality: 0.7) {
let uploadFile = GraphQLFile(fieldName: "profile_image", originalName: "profile_image", mimeType: "image/jpeg", data: imageData)
let uploadPhotoMutation = UploadProfilePhotoMutation(input: SingleFileUploadInput(file: uploadFile))
Apollo.shared.client.upload(operation: uploadPhotoMutation, files: [uploadFile]) { result in
}
}
}
@PatrickAdams Do you have a version of SingleFileUploadInput which takes a GraphQL file?
@emmya There's a bit of silliness that has to be done because of the way the combination of iOS codegen and the Upload spec works. The upload documentation has an example of what you need to do.
If that doesn't help, let me know.
Yes, I've look at the documentation many times. I see in the documentation they pass the string "a" into the UploadFileMutation but the actual file is attached under the files array parameter on the Apollo upload function. I've been wondering if its possible @emmya is just grabbing the wrong value on the backend, instead of the file, she's getting the string.
There's some goofiness where the GraphQLFile's fieldName property has to precisely match the name of the field being sent to the server, or the uploader can't figure out how to replace the passed-in string with the appropriate data.
I need to upload image in following mutation
mutation updateUserProfile ($userId:ID!,$userImage:Upload,$userDetail:UserInput!){
updateUser(id:$userId,file:$userImage,user:$userDetail){
fname
lname
}
}
Can you please let me know how can I send a image data in $file
Most helpful comment
Would love to see this added