miguelgrinberg/microdot

Help: port the uploads.py example to the uploads_async.py

beyonlo opened this issue · 2 comments

Hello.

I'm trying to port the uploads.py example to works with uasyncio, but I have no success.

I changed very little parts from the original file, following others async examples. Here the uploads_async.py that I'm trying:

from microdot_asyncio import Microdot, send_file
import uasyncio as asyncio

app = Microdot()


@app.get('/')
def index(request):
    return send_file('index.html')


@app.post('/upload')
async def upload(request):
    # obtain the filename and size from request headers
    filename = request.headers['Content-Disposition'].split(
        'filename=')[1].strip('"')
    size = int(request.headers['Content-Length'])

    # sanitize the filename
    filename = filename.replace('/', '_')

    # write the file to the files directory in 1K chunks
    with open('files/' + filename, 'wb') as f:
        while size > 0:
            await asyncio.sleep_ms(30)
            chunk = request.stream.read(min(size, 1024))
            f.write(chunk) #Error happen in this line
            size -= len(chunk)

    print('Successfully saved file: ' + filename)
    return ''


if __name__ == '__main__':
    app.run(debug=True)

Error that happen on line 27 --> f.write(chunk):

$ mpremote run uploads.py 
Starting async server on 0.0.0.0:5000...
GET / 200
Traceback (most recent call last):
  File "microdot_asyncio.py", line 367, in dispatch_request
  File "microdot_asyncio.py", line 423, in _invoke_handler
  File "<stdin>", line 27, in upload
TypeError: object with buffer protocol required
POST /upload 500
GET / 200

I think that two lines below need to be awaitable as well, but I can't to figure out how to do.

chunk = request.stream.read(min(size, 1024))
f.write(chunk)

Thank you.

I can look at this later, but the stream is asynchronous and should be awaited:

chunk = await request.stream.read(min(size, 1024))

File I/O is not asynchronous, so the f.write(chunk) is fine as it is, I think.

I can look at this later, but the stream is asynchronous and should be awaited:

chunk = await request.stream.read(min(size, 1024))

With this modification, works!

Thank you!