-
-
Notifications
You must be signed in to change notification settings - Fork 2k
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
WIP: Add a better example for file upload #2401
Conversation
Codecov Report
@@ Coverage Diff @@
## master #2401 +/- ##
=======================================
Coverage 97.19% 97.19%
=======================================
Files 39 39
Lines 8159 8159
Branches 1419 1419
=======================================
Hits 7930 7930
Misses 99 99
Partials 130 130 Continue to review full report at Codecov.
|
Hmm. The code is definitely robust but the snippet goes to very low details maybe. |
Thanks @asvetlov. Do you think is too verbose or more comments/explanations outside of the code would improve this? |
I’d add note in file operations, in general case file operations block |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Example is indeed better, but I'm not sure if we should have complicated things on our docs. As more code we have in docs as more hard keep it valid. Eventually, we cannot automatically test it to make sure that doc examples are correct.
I think we should keep example in docs simple and clean, while more complicated stuff keep in examples/
directory. This code at least is possible to test.
docs/web.rst
Outdated
# /!\ Don't forget to validate your inputs /!\ | ||
async def store_multipart_handler(request): | ||
"""Handle a multipart form.""" | ||
if request.method == 'POST': |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this is a bad pattern to recommend. You should have this condition on router level.
docs/web.rst
Outdated
return web.Response(text='Thanks {} for uploading {}' | ||
.format(data['name'], data['file'])) | ||
|
||
return web.Response(body=page, content_type="text/html") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
page is not defined.
@fafhrd91 |
So:
@kxepal a small note in the official docs completed with a link to a good example in |
I think we need the docs change but it should look like: async def store_mp3_handler(request):
reader = await request.multipart()
# /!\ Don't forget to validate your inputs /!\
field = await reader.next()
assert field.name == 'name'
name = await field.read(decode=True)
field = await reader.next()
assert field.name == 'mp3'
filename = field.filename
# You cannot rely on Content-Length if transfer is chunked.
size = 0
with open(os.path.join('/spool/yarrr-media/mp3/', filename), 'wb') as f:
while True:
chunk = await field.read_chunk() # 8192 bytes by default.
if not chunk:
break
size += len(chunk)
f.write(chunk)
return web.Response(text='{} sized of {} successfully stored'
''.format(filename, size)) The key is using @kxepal does it make sense? |
@barrachri @asvetlov |
I have no strong opinion. |
The current example and @asvetlov's are very clear in showing how you can chunk files. The problem is that usually in other frameworks you don't loop or iterate on an object to get your params and the same is also true for aiohttp, with My problem was that you jump from this example mp3 = data['mp3']
# .filename contains the name of the file in string format.
filename = mp3.filename
# .file contains the actual file data that needs to be stored somewhere.
mp3_file = data['mp3'].file
content = mp3_file.read() to this example async def store_mp3_handler(request):
reader = await request.multipart()
# /!\ Don't forget to validate your inputs /!\
mp3 = await reader.next()
filename = mp3.filename
# You cannot rely on Content-Length if transfer is chunked.
size = 0
with open(os.path.join('/spool/yarrr-media/mp3/', filename), 'wb') as f:
while True:
chunk = await mp3.read_chunk() # 8192 bytes by default.
if not chunk:
break
size += len(chunk)
f.write(chunk)
return web.Response(text='{} sized of {} successfully stored'
''.format(filename, size)) and you completely miss what's going on with After I checked the implementation of I think that a simple comment will make the example more clear. async def store_mp3_handler(request):
reader = await request.multipart()
# /!\ Don't forget to validate your inputs /!\
# reader.next() will `yield` the fields of your form
field = await reader.next()
assert field.name == 'name'
name = await field.read(decode=True)
field = await reader.next()
assert field.name == 'mp3'
filename = field.filename
# You cannot rely on Content-Length if transfer is chunked.
size = 0
with open(os.path.join('/spool/yarrr-media/mp3/', filename), 'wb') as f:
while True:
chunk = await field.read_chunk() # 8192 bytes by default.
if not chunk:
break
size += len(chunk)
f.write(chunk)
return web.Response(text='{} sized of {} successfully stored'
''.format(filename, size)) |
I think now is better. Please update the RP. |
Shall I add also an example in |
Let's update |
Thanks! |
This thread has been automatically locked since there has not been any recent activity after it was closed. Please open a [new issue] for related bugs. |
What do these changes do?
Improve docs.
I think most of the time when you upload a file you also have related fields.
This PR add a general case to the docs., where you have a text field and file field.
Are there changes in behavior for the user?
No.
Related issue number
Checklist
CONTRIBUTORS.txt
changes
folder<issue_id>.<type>
for example (588.bug)issue_id
change it to the pr id after creating the pr.feature
: Signifying a new feature..bugfix
: Signifying a bug fix..doc
: Signifying a documentation improvement..removal
: Signifying a deprecation or removal of public API..misc
: A ticket has been closed, but it is not of interest to users.