Skip to content

Commit 26f8100

Browse files
committed
Merge pull request #327 from hoh/upload_nochunked
Fix file upload not chunked
2 parents 878250f + cd3fa2e commit 26f8100

File tree

2 files changed

+42
-1
lines changed

2 files changed

+42
-1
lines changed

aiohttp/client.py

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
import weakref
1010
import warnings
1111
import chardet
12+
from os import fstat
1213

1314
import aiohttp
1415
from . import hdrs, helpers, streams
@@ -383,7 +384,13 @@ def update_body_from_data(self, data):
383384
assert not isinstance(data, io.StringIO), \
384385
'attempt to send text data instead of binary'
385386
self.body = data
386-
self.chunked = True
387+
if not self.chunked and isinstance(data, io.BufferedReader):
388+
# Not chunking if content-length can be determined
389+
size = fstat(data.fileno()).st_size - data.tell()
390+
self.headers[hdrs.CONTENT_LENGTH] = str(size)
391+
self.chunked = False
392+
else:
393+
self.chunked = True
387394
if hasattr(data, 'mode'):
388395
if data.mode == 'r':
389396
raise ValueError('file {!r} should be open in binary mode'

tests/test_client.py

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
import unittest
88
import unittest.mock
99
import urllib.parse
10+
import os.path
1011

1112
import aiohttp
1213
from aiohttp.client import ClientRequest, ClientResponse
@@ -542,6 +543,39 @@ def test_chunked_length(self):
542543
self.assertEqual(req.headers['TRANSFER-ENCODING'], 'chunked')
543544
self.assertNotIn('CONTENT-LENGTH', req.headers)
544545

546+
def test_file_upload_not_chunked(self):
547+
here = os.path.dirname(__file__)
548+
fname = os.path.join(here, 'sample.key')
549+
with open(fname, 'rb') as f:
550+
req = ClientRequest(
551+
'post', 'http://python.org/',
552+
data=f)
553+
self.assertFalse(req.chunked)
554+
self.assertEqual(req.headers['CONTENT-LENGTH'],
555+
str(os.path.getsize(fname)))
556+
557+
def test_file_upload_not_chunked_seek(self):
558+
here = os.path.dirname(__file__)
559+
fname = os.path.join(here, 'sample.key')
560+
with open(fname, 'rb') as f:
561+
f.seek(100)
562+
req = ClientRequest(
563+
'post', 'http://python.org/',
564+
data=f)
565+
self.assertEqual(req.headers['CONTENT-LENGTH'],
566+
str(os.path.getsize(fname) - 100))
567+
568+
def test_file_upload_force_chunked(self):
569+
here = os.path.dirname(__file__)
570+
fname = os.path.join(here, 'sample.key')
571+
with open(fname, 'rb') as f:
572+
req = ClientRequest(
573+
'post', 'http://python.org/',
574+
data=f,
575+
chunked=True)
576+
self.assertTrue(req.chunked)
577+
self.assertNotIn('CONTENT-LENGTH', req.headers)
578+
545579
def test_expect100(self):
546580
req = ClientRequest('get', 'http://python.org/',
547581
expect100=True, loop=self.loop)

0 commit comments

Comments
 (0)