Skip to content

GraphQL multipart uploads do not contain mimetype #385

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

Closed
aalmazan opened this issue Feb 15, 2023 · 3 comments
Closed

GraphQL multipart uploads do not contain mimetype #385

aalmazan opened this issue Feb 15, 2023 · 3 comments
Labels
type: feature A new feature

Comments

@aalmazan
Copy link

Describe the bug
Currently on v3.4.0 when uploading files, a mimetype is not being provided. This seems to default files as text/plain, at least on the Apollo GraphQL server implementation I've testing against.

The transport I'm currently using is requests, however, it's probably the case on other transports as well:

https://github.com/graphql-python/gql/blob/master/gql/transport/requests.py#L185-L187
https://github.com/graphql-python/gql/blob/master/gql/transport/aiohttp.py#L276-L278

Changing the following will work for my use case (requests transport):

# original
fields[k] = (getattr(v, "name", k), v)
# new 
fields[k] = (getattr(v, "name", k), v, 'application/pdf')
# or 
fields[k] = (getattr(v, "name", k), v, USER_PROVIDED_MIMETYPE)

To Reproduce
Same as above

Expected behavior

I suspect there's two ways about this:

  1. Autodetect the file's mimetype (or have an argument somewhere that allows the user to opt-in to this behavior):
import mimetypes
mimetype, _ = mimetypes.guess_type(file.name)
  1. Allow the user to provide the mimetype manually:
# Taken from the docs on uploading files: https://gql.readthedocs.io/en/stable/usage/file_upload.html
# Single file upload
with open("YOUR_FILE_PATH", "rb") as f:
    # old
    # params = {"file": f}
    # new
    params = {"file": (f, USER_DEFINED_MIMETYPE)}
    result = client.execute(
        query, variable_values=params, upload_files=True
    )


# Multi-file upload
f1 = open("YOUR_FILE_PATH_1", "rb")
f2 = open("YOUR_FILE_PATH_2", "rb")

params = {"files": [(f1, USER_DEFINED_MIMETYPE_1), (f2, USER_DEFINED_MIMETYPE_2)]}

System info (please complete the following information):

  • OS: Ubuntu
  • Python version: 3.9.12
  • gql version: 3.4.0
  • graphql-core version:
@leszekhanusz
Copy link
Collaborator

Option 1. could be done.

Option 2. should be done another way as we are detecting the files by checking their type, and now the provided value is a tuple instead of a File object.

One way to do it would be to add a new parameter to the file object and use it if it is present.
Something like this:

with open("YOUR_FILE_PATH", "rb") as f:

    f.content_type = "application/pdf";

    params = {"file": f}
    result = client.execute(
        query, variable_values=params, upload_files=True
    )

@leszekhanusz
Copy link
Collaborator

Please check the PR #386

Only the option 2 has been retained.
Detecting the content-type depending on the filename can be done by the user if needed.

@aalmazan
Copy link
Author

@leszekhanusz Thanks for the quick PR! I created a fork that had very similar changes as well (but just for requests) and it all works well for me.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
type: feature A new feature
Projects
None yet
Development

No branches or pull requests

2 participants