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

Can't use FromFiles and FromForm in same request #248

Closed
nico-vromans opened this issue Apr 15, 2022 · 6 comments
Closed

Can't use FromFiles and FromForm in same request #248

nico-vromans opened this issue Apr 15, 2022 · 6 comments
Labels
bug 🐞 Something isn't working fixed in branch Already fixed in a branch, waiting to be merged

Comments

@nico-vromans
Copy link

nico-vromans commented Apr 15, 2022

For some reason, I can't seem to be able to perform both a multi-file upload with additional data on the same form.

Specs:

  1. Python 3.10.4 (inside virtual environment)
  2. blacksheep 1.2.5
  3. Ubuntu 20.04

Here is my html code (simplified):

<form action='/upload_files_with_additional_data' method="post" enctype='multipart/form-data'>
    <input type="file" name="files" multiple>
    
    <label for="checkbox1" class="checkbox">Checkbox 1</label>
    <input type="checkbox" name="checkbox1">

    <label for="checkbox2" class="checkbox">Checkbox 2</label>
    <input type="checkbox" name="checkbox2">

    <label for="textfield">Text field</label>
    <input type="text" id="textfield" name="textfield">

    <input type="submit" value="Submit">
</form>

Here's what I've tried (but didn't work) and what I expect would work:

@post('/upload_files_with_additional_data')
async def upload_files_with_additional_data(self, files: FromFiles, form_data: FromForm):
for file in Files:
    # do something with each file

# do something with additional form data

I've also tried using FromForm[FormData] with the following FormData:

    class FormData:
        checkbox1: bool
        checkbo2: bool
        files: list  # also tried with type hint FromFIles (and without setting files alltogether

        # def __init__(self, checkbox1: str, checkbox2: str, files):  # also tried with files: FromFiles and without entire __init__ (but that didn't work at all)
            # self.checkbox1 = bool(checkbox1)
            # self.checkbox2 = bool(checkbox2)
            # self.files = files  # also tried with FromFiles(files)

Either I can upload files, without sending additional form data (using only files: FromFiles), or I can use the form data without the files (using only form: FromForm). Combining the two doesn't work.
When using async def upload_files_with_additional_data(self, request: Request): I can get also get the form data from there using form = await request.form(), but that only works for additional data, not the files. When I try to upload files I get:

form = await request.form()
  File "blacksheep/messages.pyx", line 172, in form
  File "blacksheep/contents.pyx", line 163, in blacksheep.contents.multiparts_to_dictionary
AttributeError: 'bytes' object has no attribute 'append'

I've also tried using async def upload_files_with_additional_data(self, bytes: FromBytes): which does seem to contain all the data, but as bytes, and I've tried a few ways to convert these to what I want, but no success there either.

Is there a way of uploading both multiple files, alongside other form data (I'm fairly confident there is, but I just haven't figured it out)? If so: how should this be achieved?

@RobertoPrevato
Copy link
Member

RobertoPrevato commented Apr 15, 2022

Hi @nico-vromans!
Thank You for submitting this issue. I just verified this is a bug in the FromForm binder, the good news is that you can still use the explicit method to read the multipart data, which works:

image

    @post("/upload_files_with_additional_data")
    async def upload(self, request) -> Response:
        data = await request.multipart()
        print(data)
        return self.text("OK")

This returns a list of parts from the multi part request, with files and input. It's a lower level code API, though, closer to the shape of the message sent by browsers.

I will fix this bug as soon as possible, I think I already know what needs to be changed.
Right now it's late evening here, I'll look more into this in the weekend.

@nico-vromans
Copy link
Author

@RobertoPrevato, thanks for the quick reply. I've tested this "workaround" myself and it works beautifully. 👍🏻

@RobertoPrevato
Copy link
Member

I'm glad I could help. 🎉 These days I am working on a plugin for MkDocs to generate automatically human readable documentation from OpenAPI Documentation, so I have limited time for the web framework, but a fix will come soon.

@RobertoPrevato RobertoPrevato added the bug 🐞 Something isn't working label Apr 16, 2022
@nico-vromans
Copy link
Author

@RobertoPrevato, I'm in no rush and I fully understand having other priorities. Take your time. Good luck with MkDocs, sounds interesting 😉

RobertoPrevato added a commit that referenced this issue Apr 26, 2022
@RobertoPrevato RobertoPrevato added the fixed in branch Already fixed in a branch, waiting to be merged label Apr 26, 2022
@nico-vromans
Copy link
Author

@RobertoPrevato, awesome, thank you 👍🏻 🥳

@RobertoPrevato
Copy link
Member

RobertoPrevato commented Apr 27, 2022

@nico-vromans thank you for reporting this bug! 🎉 I'm still looking into a couple of things, then I'll publish a new version to PyPi with this fix. I have everything automated so I can release at any time to PyPi without issues.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug 🐞 Something isn't working fixed in branch Already fixed in a branch, waiting to be merged
Projects
None yet
Development

No branches or pull requests

2 participants