user1507455
user1507455

Reputation: 1133

Python: download a file from an FTP server

I'm trying to download some public data files. I screenscrape to get the links to the files, which all look something like this:

ftp://ftp.cdc.gov/pub/Health_Statistics/NCHS/nhanes/2001-2002/L28POC_B.xpt

I can't find any documentation on the Requests library website.

Upvotes: 95

Views: 184682

Answers (9)

jfs
jfs

Reputation: 414149

The requests library doesn't support ftp:// links.

To download a file from an FTP server you could use urlretrieve:

import urllib.request

urllib.request.urlretrieve('ftp://server/path/to/file', 'file')
# if you need to pass credentials:
#   urllib.request.urlretrieve('ftp://username:password@server/path/to/file', 'file')

Or urlopen:

import shutil
import urllib.request
from contextlib import closing

with closing(urllib.request.urlopen('ftp://server/path/to/file')) as r:
    with open('file', 'wb') as f:
        shutil.copyfileobj(r, f)

Python 2:

import shutil
import urllib2
from contextlib import closing

with closing(urllib2.urlopen('ftp://server/path/to/file')) as r:
    with open('file', 'wb') as f:
        shutil.copyfileobj(r, f)

Upvotes: 124

Dean Gurvitz
Dean Gurvitz

Reputation: 1072

If you want to take advantage of recent Python versions' async features, you can use aioftp (from the same family of libraries and developers as the more popular aiohttp library). Here is a code example taken from their client tutorial:

client = aioftp.Client()
await client.connect("ftp.server.com")
await client.login("user", "pass")
await client.download("tmp/test.py", "foo.py", write_into=True)

Upvotes: 4

Gaurav Shrivastava
Gaurav Shrivastava

Reputation: 943

Try using the wget library for python. You can find the documentation for it here.

import wget
link = 'ftp://example.com/foo.txt'
wget.download(link)

Upvotes: 18

GoatWang
GoatWang

Reputation: 105

urlretrieve is not work for me, and the official document said that They might become deprecated at some point in the future.

import shutil 
from urllib.request import URLopener
opener = URLopener()
url = 'ftp://ftp_domain/path/to/the/file'
store_path = 'path//to//your//local//storage'
with opener.open(url) as remote_file, open(store_path, 'wb') as local_file:
    shutil.copyfileobj(remote_file, local_file)

Upvotes: 1

Rakesh
Rakesh

Reputation: 82755

You Can Try this

import ftplib

path = 'pub/Health_Statistics/NCHS/nhanes/2001-2002/'
filename = 'L28POC_B.xpt'

ftp = ftplib.FTP("Server IP") 
ftp.login("UserName", "Password") 
ftp.cwd(path)
ftp.retrbinary("RETR " + filename, open(filename, 'wb').write)
ftp.quit()

Upvotes: 73

Nelson
Nelson

Reputation: 29706

As several folks have noted, requests doesn't support FTP but Python has other libraries that do. If you want to keep using the requests library, there is a requests-ftp package that adds FTP capability to requests. I've used this library a little and it does work. The docs are full of warnings about code quality though. As of 0.2.0 the docs say "This library was cowboyed together in about 4 hours of total work, has no tests, and relies on a few ugly hacks".

import requests, requests_ftp
requests_ftp.monkeypatch_session()
response = requests.get('ftp://example.com/foo.txt')

Upvotes: 4

Roman Podlinov
Roman Podlinov

Reputation: 24944

    import os
    import ftplib
    from contextlib import closing

    with closing(ftplib.FTP()) as ftp:
        try:
            ftp.connect(host, port, 30*5) #5 mins timeout
            ftp.login(login, passwd)
            ftp.set_pasv(True)
            with open(local_filename, 'w+b') as f:
                res = ftp.retrbinary('RETR %s' % orig_filename, f.write)

                if not res.startswith('226 Transfer complete'):
                    print('Downloaded of file {0} is not compile.'.format(orig_filename))
                    os.remove(local_filename)
                    return None

            return local_filename

        except:
                print('Error during download from FTP')

Upvotes: 7

Victor Gavro
Victor Gavro

Reputation: 1407

urllib2.urlopen handles ftp links.

Upvotes: 2

Parker
Parker

Reputation: 8851

Use urllib2. For more specifics, check out this example from doc.python.org:

Here's a snippet from the tutorial that may help

import urllib2

req = urllib2.Request('ftp://example.com')
response = urllib2.urlopen(req)
the_page = response.read()

Upvotes: 7

Related Questions