3

I'm trying to download a binary file and save it with its original name on the disk (linux).

Any ideas?

import requests

params = {'apikey': 'xxxxxxxxxxxxxxxxxxx', 'hash':'xxxxxxxxxxxxxxxxxxxxxxxxx'}
response = requests.get('https://www.test.com/api/file/download', params=params)
downloaded_file = response.content

if response.status_code == 200:
    with open('/tmp/', 'wb') as f:
        f.write(response.content)
petezurich
  • 9,280
  • 9
  • 43
  • 57
bugnet17
  • 173
  • 1
  • 1
  • 12

1 Answers1

8

From your clarification in the comments, your issue is that you want to keep the file's original name.

If the URL directs to the raw binary data, then the last part of the URL would be its "original name", hence you can get that by parsing the URL as follows:

local_filename = url.split('/')[-1]

To put this into practice, and considering the context of the question, here is the code that does exactly what you need, copied as it is from another SO question:

local_filename = url.split('/')[-1]
# NOTE the stream=True parameter
r = requests.get(url, stream=True)
with open(local_filename, 'wb') as f:
    for chunk in r.iter_content(chunk_size=1024): 
        if chunk: # filter out keep-alive new chunks
            f.write(chunk)
            #f.flush() commented by recommendation from J.F.Sebastian
return local_filename

Couldn't post this as a comment, so had to put it in an answer. I hope I have been clear enough. Tell me if you have any issues with the code. And when the issue is resolved, please also inform me so I can then delete this as it's already been answered.

EDIT

Here is a version for your code:

import requests

url = 'https://www.test.com/api/file/download'
params = {'apikey': 'xxxxxxxxxxxxxxxxxxx', 'hash':'xxxxxxxxxxxxxxxxxxxxxxxxx', 'stream':True}
response = requests.get(url, params=params)

local_filename = url.split('/')[-1]
totalbits = 0
if response.status_code == 200:
    with open(local_filename, 'wb') as f:
        for chunk in response.iter_content(chunk_size=1024):
            if chunk:
                totalbits += 1024
                print("Downloaded",totalbits*1025,"KB...")
                f.write(chunk)

NOTE: if you don't want it to show progress, just remove the printstatement on line 15. This was tested using this url: https://imagecomics.com/uploads/releases/_small/DeadRabbit-02_cvr.jpg and it seemed to work pretty well. Again, if you have any issues, just comment down below.

  • Can you show an example with my code(in the question)? – bugnet17 Nov 05 '18 at 08:27
  • @bugnet17 sorry for the late reply I've made a version of this for your code in the question and posted it. Code was tested with this url: https://imagecomics.com/uploads/releases/_small/DeadRabbit-02_cvr.jpg the image was downloaded to my desktop correctly with the same original name. –  Nov 06 '18 at 12:04
  • @Dennis Patterson you are mixing up bits and bytes on your calculation. Also a buffer size of 1KB is pretty small for the typical file size and bandwidth nowadays: You do not want to choke the download just to print progress several times per second! Also you are multiplying by 1025 instead of dividing by 1025 to get the total bytes downloaded: What's the logic behind that? – NotGaeL Feb 14 '21 at 17:21
  • (P.S: Also it'd be best to just accumulate len(chunk) for accuracy on total bytes downloaded or at least adjust for last chunk's length) – NotGaeL Feb 14 '21 at 17:25
  • To add on, you probably want to do a os.fsync(f.fileno()) to ensure all buffers are empty. – LT21j Mar 12 '21 at 19:20