My goal is to do a PUT of part of a file using requests and stream the file (i.e., not load it into memory and then do the PUT).
This page explains how you would do that for an entire file:
Requests supports streaming uploads, which allow you to send large streams or files without reading them into memory. To stream and upload, simply provide a file-like object for your body:
with open('massive-body', 'rb') as f:
requests.post('http://some.url/streamed', data=f)
However in my case I want to only send one chunk of the file. Is there a way to accomplish this?
In concept, something like:
with open('massive-body', 'rb') as f:
requests.post('http://some.url/streamed', data=f.read(chunksize))
If you want to send the file as the only content then you can directly add it as the request body and you set the Content-Type header to the MIME type of the file you are sending. The file name can be added in the Content-Disposition header.
Run the Application by running “python multiplefilesupload.py”. Go to browser and type “http://localhost:5000”, you will see “upload files” in browser.
Method 1: Using the Python's os Module: Also, the enctype attribute with "multi-part/form-data" value will help the HTML form to upload a file. Lastly, we need the input tag with the filename attribute to upload the file we want. Lastly, we need the input tag with the filename attribute to upload the file we want.
Based off Greg's answers to my questions I think the following will work best:
First you'll need something to wrap your open file so that it limits how much data can be read:
class FileLimiter(object):
def __init__(self, file_obj, read_limit):
self.read_limit = read_limit
self.amount_seen = 0
self.file_obj = file_obj
# So that requests doesn't try to chunk the upload but will instead stream it:
self.len = read_limit
def read(self, amount=-1):
if self.amount_seen >= self.read_limit:
return b''
remaining_amount = self.read_limit - self.amount_seen
data = self.file_obj.read(min(amount, remaining_amount))
self.amount_seen += len(data)
return data
This should roughly work as a good wrapper object. Then you would use it like so:
with open('my_large_file', 'rb') as file_obj:
file_obj.seek(my_offset)
upload = FileLimiter(file_obj, my_chunk_limit)
r = requests.post(url, data=upload, headers={'Content-Type': 'application/octet-stream'})
The headers are obviously optional, but when streaming data to a server, it's a good idea to be a considerate user and tell the server what the type of the content is that you're sending.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With