Description
Long story short
Using part.set_content_disposition for some multipart file stuff, couldn't get it to work.
So I checked the part header, which is as I expected and then made a fake writer to check what the payload being sent actually was. The content disposition in the payload doesn't at all match what I have set in the part.
Expected behaviour
The content disposition in the payload is as set in the part.
Actual behaviour
It appears to generate a fresh content disposition.
Steps to reproduce
class Writer:
def __init__(self):
self.buffer = ""
async def write(self, stuff):
self.buffer += stuff.decode('utf-8','ignore')
def done(self):
print(self.buffer[:300])
# Generate multipart
with aiohttp.MultipartWriter('form-data') as mp:
part = mp.append(open(path, 'rb'))
part.set_content_disposition(
'form-data',
quote_fields=False,
name='files[]',
filename=os.path.split(path)[1]
)
# Fix aiohttp being retarded
part._headers['Content-Disposition'] = part._headers['Content-Disposition'].split(" filename*=utf-8", 1)[0]
print("\n", part._headers['Content-Disposition'], "\n")
w = Writer()
await mp.write(w)
w.done()
Your environment
Aiohttp 3.2.1
Python 3.6
macOS 10.13.4
The issue (as far as I can tell)
https://github.com/aio-libs/aiohttp/blob/master/aiohttp/multipart.py#L754-L755
It appears there that the payload headers are saved separately and so no matter what you do to the returned part after it's appended, the headers will never actually be updated in the multipart.
Hotfix (until this issue is resolved)
Create your payload yourself, set headers etc. before you append to the multipart.
eg.
# Hotfix
from multidict import CIMultiDict
payload = aiohttp.payload.get_payload(open(path, 'rb'), headers=CIMultiDict())
payload.set_content_disposition(
'form-data',
quote_fields=False,
name='files[]',
filename=os.path.split(path)[1]
)
payload._headers['Content-Disposition'] = payload._headers['Content-Disposition'].split(" filename*=utf-8", 1)[0]
# Add part to multipart
part = mp.append(payload)