Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Problem uploading a file with GraphQLFile #695

Closed
Cleversou1983 opened this issue Aug 6, 2019 · 33 comments
Closed

Problem uploading a file with GraphQLFile #695

Cleversou1983 opened this issue Aug 6, 2019 · 33 comments
Labels
docs Focuses on documentation changes question Issues that have a question which should be addressed
Milestone

Comments

@Cleversou1983
Copy link

Currently I have a mutation like this:

mutation uploadFile($file:Upload!) {

}

extension UploadFileMutation {
public typealias Upload = GraphQLFile
}

I've made an extension, so the compiler doesn't complain about the type

When I try use GraphQLFile as parameter
Cannot convert value of type 'UploadFileMutation.Upload' (aka 'GraphQLFile') to expected dictionary value type 'Optional'

I couldn't upload with HTTPTransportNetwork as well.. Could someone give some hints?

Thanks!

@designatednerd
Copy link
Contributor

This is related to #681 (missing documentation).

If you take a look at the expected string in the multi-part form data and the docs for the multi-part upload spec you can see the type of query you'd want to have is something like this:

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

That singleUpload is the name of the method your schema provides for uploading the file. The upload method should take care of doing all the multipart handling nonsense for you.

@designatednerd designatednerd added docs Focuses on documentation changes question Issues that have a question which should be addressed labels Aug 6, 2019
@Cleversou1983
Copy link
Author

Thanks a lot for your help, Ellen... I hope the example arrive soon, I still don't have success sending GraphQLFile to a GraphQL on a rails server...
Cheers!
Cleverson

@designatednerd
Copy link
Contributor

Is the issue you're having on the server side? If so, can we close this issue out?

If not, can you be more specific about what's going wrong?

@Cleversou1983
Copy link
Author

To be honest, I'm not sure if is server side issue...

I'm doing:
let file= GraphQLFile(fieldName: "file", originalName: "file", mimeType: "image/png", data: imageData!)
let mutation = UploadFileMutation(file: file)

I then create an extension
extension UploadFileMutation {
public typealias Upload = GraphQLFile
}

Then in this line,
public var variables: GraphQLMap? {
return ["file": file]
}

I get this error
Cannot convert value of type 'UploadFileMutation.Upload' (aka 'GraphQLFile') to expected dictionary value type 'Optional'

I'm totally lost!
Thanks a lot, Ellen

@designatednerd
Copy link
Contributor

You should not need to create that typealias yourself - can you post the generated code for UploadFileMutation please?

@Cleversou1983
Copy link
Author

Sure! Thanks a lot, Ellen! Cheers!

public final class UploadFileMutation: GraphQLMutation {
public let operationDefinition =
"mutation UploadFile($file: Upload!) {\n uploadFile(input: {file: $file}) {\n __typename\n attachment {\n __typename\n id\n }\n errors\n }\n}"

public let operationName = "UploadFile"

public var file: Upload

public init(file: Upload) {
self.file = file
}

public var variables: GraphQLMap? {
return ["file": file]
}

public struct Data: GraphQLSelectionSet {
public static let possibleTypes = ["Mutation"]

public static let selections: [GraphQLSelection] = [
  GraphQLField("uploadFile", arguments: ["input": ["file": GraphQLVariable("file")]], type: .object(UploadFile.selections)),
]

public private(set) var resultMap: ResultMap

public init(unsafeResultMap: ResultMap) {
  self.resultMap = unsafeResultMap
}

public init(uploadFile: UploadFile? = nil) {
  self.init(unsafeResultMap: ["__typename": "Mutation", "uploadFile": uploadFile.flatMap { (value: UploadFile) -> ResultMap in value.resultMap }])
}

public var uploadFile: UploadFile? {
  get {
    return (resultMap["uploadFile"] as? ResultMap).flatMap { UploadFile(unsafeResultMap: $0) }
  }
  set {
    resultMap.updateValue(newValue?.resultMap, forKey: "uploadFile")
  }
}

public struct UploadFile: GraphQLSelectionSet {
  public static let possibleTypes = ["UploadFilePayload"]

  public static let selections: [GraphQLSelection] = [
    GraphQLField("__typename", type: .nonNull(.scalar(String.self))),
    GraphQLField("attachment", type: .object(Attachment.selections)),
    GraphQLField("errors", type: .list(.nonNull(.scalar(String.self)))),
  ]

  public private(set) var resultMap: ResultMap

  public init(unsafeResultMap: ResultMap) {
    self.resultMap = unsafeResultMap
  }

  public init(attachment: Attachment? = nil, errors: [String]? = nil) {
    self.init(unsafeResultMap: ["__typename": "UploadFilePayload", "attachment": attachment.flatMap { (value: Attachment) -> ResultMap in value.resultMap }, "errors": errors])
  }

  public var __typename: String {
    get {
      return resultMap["__typename"]! as! String
    }
    set {
      resultMap.updateValue(newValue, forKey: "__typename")
    }
  }

  public var attachment: Attachment? {
    get {
      return (resultMap["attachment"] as? ResultMap).flatMap { Attachment(unsafeResultMap: $0) }
    }
    set {
      resultMap.updateValue(newValue?.resultMap, forKey: "attachment")
    }
  }

  public var errors: [String]? {
    get {
      return resultMap["errors"] as? [String]
    }
    set {
      resultMap.updateValue(newValue, forKey: "errors")
    }
  }

  public struct Attachment: GraphQLSelectionSet {
    public static let possibleTypes = ["Attachment"]

    public static let selections: [GraphQLSelection] = [
      GraphQLField("__typename", type: .nonNull(.scalar(String.self))),
      GraphQLField("id", type: .nonNull(.scalar(GraphQLID.self))),
    ]

    public private(set) var resultMap: ResultMap

    public init(unsafeResultMap: ResultMap) {
      self.resultMap = unsafeResultMap
    }

    public init(id: GraphQLID) {
      self.init(unsafeResultMap: ["__typename": "Attachment", "id": id])
    }

    public var __typename: String {
      get {
        return resultMap["__typename"]! as! String
      }
      set {
        resultMap.updateValue(newValue, forKey: "__typename")
      }
    }

    public var id: GraphQLID {
      get {
        return resultMap["id"]! as! GraphQLID
      }
      set {
        resultMap.updateValue(newValue, forKey: "id")
      }
    }
  }
}

}
}

@kimdv
Copy link
Contributor

kimdv commented Aug 7, 2019

Hi!
Hope this can help

This is my mutation

mutation AddImage($id: ID!, $image: ImageInput!) {
  addImage(id: $id, image: $image) {
    ...ImageFragment
  }
}

This is my swift method:

    @discardableResult
    func addImage(id: String,
                  image: Data,
                  source: String?,
                  copyright: String,
                  completion: @escaping (Swift.Result<ImageFragment, SupertrendsClientError>) -> Void) -> Cancellable {
        let name = UUID().uuidString
        let file = GraphQLFile(fieldName: name, originalName: name, mimeType: "image/jpeg", data: image)
        let imageInput = ImageInput(copyright: copyright, source: source, upload: name, url: nil)
        let query = AddImageMutation(id: id, image: imageInput)

        return performUpload(query: query, files: [file], resultMap: { $0.addImage?.fragments.imageFragment }, completion: completion)
    }

performUpload is just a generic method for sharing the upload function.

I have also added a type alias for my Upload file public typealias Upload = String

@Cleversou1983
Copy link
Author

@kimdv Thanks a lot friend! I'll try that!

One question the performUpload you've talked about just execute te mutation within Apollo? Thanks!!!!!!!!

@kimdv
Copy link
Contributor

kimdv commented Aug 7, 2019

    private func performUpload<Query: GraphQLMutation, Res>(query: Query,
                                                            files: [GraphQLFile],
                                                            resultMap: @escaping (Query.Data) -> Res?,
                                                            completion: @escaping (Swift.Result<Res, SupertrendsClientError>) -> Void) -> Cancellable {
        return networkTransport.upload(operation: query, files: files) { result in
            switch result {
            case .success(let data):
                if let object = try? Query.Data.init(jsonObject: data.body),
                    let model = resultMap(object) {
                    completion(.success(model))
                } else {
                    completion(.failure(SupertrendsClientError.unknown))
                }
            case .failure(let error):
                completion(.failure(SupertrendsClientError.unknown))
            }
        }
    }

Here it is

@kimdv
Copy link
Contributor

kimdv commented Aug 7, 2019

And related to this.

@designatednerd the reason I first had added the upload method to ApolloClient was for the same result type. Now we get a more generic one, and not the same as "normal" mutation.

I think we should make is similar somehow

@Cleversou1983
Copy link
Author

@kimdv Thanks a lot my friend, I'll try that now, I really appreciate your help!
Cheers!

@Cleversou1983
Copy link
Author

Cleversou1983 commented Aug 7, 2019

@kdvtrifork Can you give me a little help with that?
I got a response from my backend developer, my mutation is now returning this, shouldn't the. be Content-Disposition: form-data, multipart-data instead?

2019-08-07T12:55:07.405171+00:00 app[web.1]: UploadFile
2019-08-07T12:55:07.405173+00:00 app[web.1]: --apollo-ios.boundary.0D94B585-41E9-42A6-B29F-7BBAE60AF397
2019-08-07T12:55:07.405175+00:00 app[web.1]: Content-Disposition: form-data; name="file"; filename="file"
2019-08-07T12:55:07.405176+00:00 app[web.1]: Content-Type: image/jpeg

////
let fileFieldName = "file"
let file = GraphQLFile(fieldName: fileFieldName, originalName: fileFieldName, mimeType: "image/jpeg", data: imageData)

        let uploadInput = UploadFileMutation(file: fileFieldName)

let configuration = URLSessionConfiguration.default
let transport = HTTPNetworkTransport(url: AppParameters.APIPublicUrl, configuration: configuration)
let upload = transport.upload(operation: uploadInput, files: [file]) { (result) in
///////
}

Thanks a lot brother!
Cheers!

@kimdv
Copy link
Contributor

kimdv commented Aug 7, 2019

I don't understand the question?

The mutation and file creation looks good.
Is the server not accepting it?

@Cleversou1983
Copy link
Author

@kimdv On the server, instead of multipart / form-data, the server is getting:
Content-Disposition: form-data; name="file"; filename="file"

@kimdv
Copy link
Contributor

kimdv commented Aug 7, 2019

The implication is based on this specification

Does the server also follow that?

@Cleversou1983
Copy link
Author

Cleversou1983 commented Aug 7, 2019

@kdvtrifork I believe so, when I'm using Altair GraphQL, I'm able to perform uploads...
My code is this, maybe I'm still doing something wrong? Many many thanks, Kim!

if let imageData = image.jpegData(compressionQuality: 0.7) {

        self.UIManager.disableUI()

        let fileFieldName   = "file"
        let file            = GraphQLFile(fieldName: fileFieldName, originalName: fileFieldName, mimeType: "image/jpeg", data: imageData)

        let uploadInput = UploadFileInput(clientId: AppParameters.clientId,
                                          clientSecret: AppParameters.clientSecret,
                                          file: fileFieldName)
        let uploadMutation = UploadFileMutation(input: uploadInput)
        
        let configuration = URLSessionConfiguration.default
        configuration.httpAdditionalHeaders = [
            "Language" : "en"
        ]

        let transport   = HTTPNetworkTransport(url: AppParameters.APIPublicUrl, configuration: configuration)
        let upload      = transport.upload(operation: uploadMutation, files: [file]) { (result) in
             self.UIManager.enableUI()

            switch result {
            case .success(let data):
                print("Success")
                dump(data)
            case .failure(let error):
                print("Error \(error.localizedDescription)")
            }
        }
    }

@designatednerd
Copy link
Contributor

Looks like Altair is using the FormData type to do uploads - under the hood, it looks like that's using multipart/form-data rather than just form-data.

I would talk to your backend person about the spec - all of the examples there use form-data rather than multipart/form-data.

@Cleversou1983
Copy link
Author

Hi Ellen... The awkward thing is that the CURL example from specifications work with our backend...

curl http://madari-staging.herokuapp.com/graphql
-F operations='{ "query": "mutation($image: Upload!, $clientId: String!, $clientSecret: String!) { uploadFile( input: { file: $image clientId: $clientId, clientSecret: $clientSecret } ) { errors attachment { id } } }", "variables": { "clientId": "fGwoCunPSgA0uDnaW8I_NhMtOemN-zYuEb6HKaMlfvs", "clientSecret": "wFQkIOYzrAh6ulcJLTEvKQjW4aP5hBAPWzNxw5j7pQw", "image": null } }'
-F map='{ "0": ["variables.image"] }'
-F 0=@oren\ Logo.png

Thanks again!

@Rudiney
Copy link

Rudiney commented Aug 8, 2019

The "back-end guy" checking in here to help my co-work @Cleversou1983 on this issue.
AFAIK the back-end should follow the specs as we are using the suggested jetruby/apollo_upload_server-ruby ruby gem.

The spec shows a cURL example we could successfully run (as above) so maybe it helps lighten up the problem here. That is a public available version we can all use if it helps.

Comparing the server log between the cURL and the request coming from the iOS client show an interesting difference:

cURL shows:

[2019-08-07T18:15:45.805101 #4]  INFO -- : [cf2ffd25-3124-4752-81df-fcee3ce30cd1] Processing by Public::GraphqlController#execute as */*
[2019-08-07T18:15:45.805334 #4]  INFO -- : [cf2ffd25-3124-4752-81df-fcee3ce30cd1]   Parameters: {"operations"=>"{ \"query\": \"mutation($image: Upload!, $clientId: String!, $clientSecret: String!) { uploadFile( input: { file: $image  clientId: $clientId,  clientSecret: $clientSecret  }  ) { errors  attachment { id } } }\", \"variables\": { \"clientId\": \"fGwoCunPSgA0uDnaW8I_NhMtOemN-zYuEb6HKaMlfvs\", \"clientSecret\": \"wFQkIOYzrAh6ulcJLTEvKQjW4aP5hBAPWzNxw5j7pQw\", \"image\": null } }", "map"=>"{ \"0\": [\"variables.image\"] }", "0"=>#<ActionDispatch::Http::UploadedFile:0x00007ffa8c869f50 @tempfile=#<Tempfile:/tmp/RackMultipart20190807-4-16tyea8.png>, @original_filename="Oren Logo.png", @content_type="application/octet-stream", @headers="Content-Disposition: form-data; name=\"0\"; filename=\"Oren Logo.png\"\r\nContent-Type: application/octet-stream\r\n">, "query"=>"mutation($image: Upload!, $clientId: String!, $clientSecret: String!) { uploadFile( input: { file: $image  clientId: $clientId,  clientSecret: $clientSecret  }  ) { errors  attachment { id } } }", "variables"=>{"clientId"=>"fGwoCunPSgA0uDnaW8I_NhMtOemN-zYuEb6HKaMlfvs", "clientSecret"=>"wFQkIOYzrAh6ulcJLTEvKQjW4aP5hBAPWzNxw5j7pQw", "image"=>#<ActionDispatch::Http::UploadedFile:0x00007ffa8c869f50 @tempfile=#<Tempfile:/tmp/RackMultipart20190807-4-16tyea8.png>, @original_filename="Oren Logo.png", @content_type="application/octet-stream", @headers="Content-Disposition: form-data; name=\"0\"; filename=\"Oren Logo.png\"\r\nContent-Type: application/octet-stream\r\n">}}
........

[2019-08-07T18:15:46.777065 #4]  INFO -- : [cf2ffd25-3124-4752-81df-fcee3ce30cd1] [ActiveJob] Enqueued ActiveStorage::AnalyzeJob (Job ID: 3a71cfa8-e599-49ea-b013-da68f3e26ea3) to Async(default) with arguments: #<GlobalID:0x00007ffa8c6c1bd0 @uri=#<URI::GID gid://madari/ActiveStorage::Blob/58>>
[2019-08-07T18:15:46.779570 #4]  INFO -- : [cf2ffd25-3124-4752-81df-fcee3ce30cd1] Completed 200 OK in 974ms (Views: 0.3ms | ActiveRecord: 18.6ms)

Request from iOS shows:

...                                            A LOT MORE OF THESE ODD CHARACTERS
2019-08-07T18:14:07.336809+00:00 app[web.1]: ��r��X��F�y2��+g$�
2019-08-07T18:14:07.336810+00:00 app[web.1]: rZ�>��޷�����<p=��G$Z6��  �\�TN�d
                                                                               ���o���PG�r�f
2019-08-07T18:14:07.336812+00:00 app[web.1]: m�|�6�rM2�FLO��
2019-08-07T18:14:07.336813+00:00 app[web.1]: ���1C�6s��|�w�cN���[�zW8�3��[���s��$"3!<��c�Cn%
                                                                                            �N@�닄�qԚd�a2�禘J�y�3d�.��ϔ��cV�7w�8�3�9�!,2�c�2H��\m�k�x=+��J�v�������:���8�37SVev�0Gzʸ|-|�G�ެ�#��'9����y�7�S�f��-Up�r�㹪N�d�G���J�v
2019-08-07T18:14:07.336815+00:00 app[web.1]: rEr�G��B�[��
2019-08-07T18:14:07.336816+00:00 app[web.1]: --apollo-ios.boundary.0C6D05A8-D24A-4710-AAB3-A5B17932B9BF--
2019-08-07T18:14:07.337714+00:00 app[web.1]: F, [2019-08-07T18:14:07.337599 #4] FATAL -- : [0be539e3-58c8-40a6-8e3f-191a69c56806]
2019-08-07T18:14:07.337783+00:00 app[web.1]: F, [2019-08-07T18:14:07.337729 #4] FATAL -- : [0be539e3-58c8-40a6-8e3f-191a69c56806] ActionDispatch::Http::Parameters::ParseError (765: unexpected token at '--apollo-ios.boundary.0C6D05A8-D24A-4710-AAB3-A5B17932B9BF
2019-08-07T18:14:07.337785+00:00 app[web.1]: Content-Disposition: form-data; name="query"
2019-08-07T18:14:07.337787+00:00 app[web.1]:
2019-08-07T18:14:07.337788+00:00 app[web.1]: mutation UploadFile($image: Upload!, $clientID: String!, $clientSecret: String!) {
2019-08-07T18:14:07.337790+00:00 app[web.1]: uploadFile(input: {file: $image, clientId: $clientID, clientSecret: $clientSecret}) {
2019-08-07T18:14:07.337792+00:00 app[web.1]: __typename
2019-08-07T18:14:07.337793+00:00 app[web.1]: attachment {
2019-08-07T18:14:07.337795+00:00 app[web.1]: __typename
2019-08-07T18:14:07.337796+00:00 app[web.1]: id
2019-08-07T18:14:07.337798+00:00 app[web.1]: }
2019-08-07T18:14:07.337799+00:00 app[web.1]: errors
2019-08-07T18:14:07.337800+00:00 app[web.1]: }
2019-08-07T18:14:07.337802+00:00 app[web.1]: }
2019-08-07T18:14:07.337804+00:00 app[web.1]: --apollo-ios.boundary.0C6D05A8-D24A-4710-AAB3-A5B17932B9BF
2019-08-07T18:14:07.337805+00:00 app[web.1]: Content-Disposition: form-data; name="variables"
2019-08-07T18:14:07.337807+00:00 app[web.1]:
2019-08-07T18:14:07.337808+00:00 app[web.1]: {"image":"","clientID":"k6PPvCVbzpCuXik5WMpSLoIcPWqbIK-Ot5Rm7Z8cM6E","clientSecret":"YlxQChkVtQ5rzeGh0FdzfsQJVxHlOHFICfNg5QcQK8g"}
2019-08-07T18:14:07.337810+00:00 app[web.1]: --apollo-ios.boundary.0C6D05A8-D24A-4710-AAB3-A5B17932B9BF
2019-08-07T18:14:07.337811+00:00 app[web.1]: Content-Disposition: form-data; name="operationName"
2019-08-07T18:14:07.337813+00:00 app[web.1]:
2019-08-07T18:14:07.337814+00:00 app[web.1]: UploadFile
2019-08-07T18:14:07.337816+00:00 app[web.1]: --apollo-ios.boundary.0C6D05A8-D24A-4710-AAB3-A5B17932B9BF
2019-08-07T18:14:07.337817+00:00 app[web.1]: Content-Disposition: form-data; name="file"; filename="file"
2019-08-07T18:14:07.337819+00:00 app[web.1]: Content-Type: image/jpeg
2019-08-07T18:14:07.337820+00:00 app[web.1]:
2019-08-07T18:14:07.337822+00:00 app[web.1]: ����'):
2019-08-07T18:14:07.337826+00:00 app[web.1]: F, [2019-08-07T18:14:07.337787 #4] FATAL -- : [0be539e3-58c8-40a6-8e3f-191a69c56806]
2019-08-07T18:14:07.337917+00:00 app[web.1]: F, [2019-08-07T18:14:07.337848 #4] FATAL -- : [0be539e3-58c8-40a6-8e3f-191a69c56806] vendor/bundle/ruby/2.5.0/gems/actionpack-5.2.3/lib/action_dispatch/http/parameters.rb:117:in `rescue in parse_formatted_parameters'
2019-08-07T18:14:07.337920+00:00 app[web.1]: [0be539e3-58c8-40a6-8e3f-191a69c56806] vendor/bundle/ruby/2.5.0/gems/actionpack-5.2.3/lib/action_dispatch/http/parameters.rb:111:in `parse_formatted_parameters'
2019-08-07T18:14:07.337922+00:00 app[web.1]: [0be539e3-58c8-40a6-8e3f-191a69c56806] vendor/bundle/ruby/2.5.0/gems/actionpack-5.2.3/lib/action_dispatch/http/request.rb:381:in `block in POST'
2019-08-07T18:14:07.337925+00:00 app[web.1]: [0be539e3-58c8-40a6-8e3f-191a69c56806] vendor/bundle/ruby/2.5.0/gems/rack-2.0.7/lib/rack/request.rb:59:in `fetch'
2019-08-07T18:14:07.337927+00:00 app[web.1]: [0be539e3-58c8-40a6-8

@Rudiney
Copy link

Rudiney commented Aug 8, 2019

So im not sure what is the problem here but there is something strange if the request... Again, the above CURL should work publicly if it helps us debug. I thing the server is ok...

hope it help guys, thanks!

@designatednerd
Copy link
Contributor

designatednerd commented Aug 8, 2019

OK so I see a couple possibilities here:

  • Is the boundary coming through correctly with the header? The "unexpected token" seems like maybe it's related to that.
  • Looks like curl is uploading the data as application/octet-stream rather than image/jpg. What happens if you change the MIME type of the GraphQLFile to that?

@designatednerd
Copy link
Contributor

OK - well, I figured at least one thing out that I'll be fixing - it looks like the Content-Type is getting hammered with application/json even after it's been set.

@kimdv I could use your help on another bit - looking at what comes out of using RequestCreator.requestMultipartFormData, I'm not able to see where things are getting converted to a map like you're using in the multipart-form tests. Did I break something when I pulled that out into a separate piece?

@kimdv
Copy link
Contributor

kimdv commented Aug 12, 2019

@designatednerd There is something a line 37.
That should convert a GraphQLMap.

But I also thing that map is just a name.
But correct me if I'm wrong! 🤷‍♂️

@designatednerd
Copy link
Contributor

Yeah I've been working on testing with yoga's upload engine and it would reject anything that didn't have a section explicitly named map.

Working on a PR.

@kimdv
Copy link
Contributor

kimdv commented Aug 12, 2019

hmm okay!
We use absinthe for our backend. If that can help..

@designatednerd
Copy link
Contributor

For everyone here: #707 should help significantly with a lot of these issues.

@designatednerd designatednerd added this to the 0.15.0 milestone Aug 14, 2019
@designatednerd
Copy link
Contributor

Significant changes shipping with 0.15.0 - @Cleversou1983 if you're still having trouble after that upgrade and you can't work it out with your BE dev, please open a new issue and we'll try to figure it out.

@DeekshaApptunix
Copy link

I need to upload image with following mutation in swift 5.0

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

@Cleversou1983
Copy link
Author

@DeekshaApptunix You should use GraphQLFile, like this:
let photoData = photo.jpegData(compressionQuality: 0.8)!
let file = GraphQLFile(fieldName: "file", originalName: "file.jpg", mimeType: "image/jpeg", data: photoData)

In your mutation, pass as the file parameter, the name of the parameter, for example:
updateUser(id:$userId,file:"file",user:$userDetail)

@DeekshaApptunix
Copy link

@Cleversou1983 If I am sending data like you suggested then I am also getting error

if let imageData = userImgVew.image?.jpegData(compressionQuality: 0.7) {
let file = GraphQLFile(fieldName: name, originalName: name, mimeType: "image/jpeg", data:imageData)
apollo.perform(mutation:UpdateUserProfileMutation.init(userId:id, userImage:"(file)", userDetail: userDict))

Error : "createReadStream is not a function"

@designatednerd
Copy link
Contributor

fieldName needs to be the name of the field being uploaded, and you need to use the upload function rather than the perform(mutation: function in order to perform an upload.

@DeekshaApptunix
Copy link

I need to upload in this mutation

if let logoData = btnCommunity.currentImage?.jpegData(compressionQuality: 0.8) , let coverData = coverImage.image?.jpegData(compressionQuality: 0.8) {
let coverFile = GraphQLFile(fieldName:"file", originalName:"cover.png", mimeType: "image/jpeg", data:coverData)
let logoFile = GraphQLFile(fieldName:"logo", originalName:"logo.png", mimeType: "image/jpeg", data:logoData)
}

let uploadData = CreateCommunityMutation(communityDetail:communityDetail, invitedusers: invitedUser, file: "(file)", communityLogo: "(logo)")
apollo.upload(operation:uploadData, files:[]){ result in

Here is my mutation for the same

mutation createCommunity($communityDetail:CommunityInput!,$invitedusers:[ID],$file:Upload,$communityLogo:Upload){
createCommunity(community:$communityDetail , users:$invitedusers , file:$file , logo:$communityLogo ){
id
name
}
}

I am getting following error

createReadStream is not a function

@designatednerd
Copy link
Contributor

@DeekshaApptunix let's try to concentrate your problems in issue #938 please. Thank you!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
docs Focuses on documentation changes question Issues that have a question which should be addressed
Projects
None yet
Development

No branches or pull requests

5 participants