1

I'm trying to download a zip file via ftp, but then extract the files inside without ever actually saving the zip. Any idea how I do this?

Subbarker
  • 157
  • 2
  • 10

4 Answers4

6

use zipfile.open

it opens a member from the archive into memory. Since ZipFile accepts any file-like object as parameter, you may get it from many sources, like HTTP/FTP servers

import urllib
import io
from zipfile import ZipFile

mysock = urllib.urlopen('ftp://ftp.yourhost.com/spam.zip')  // check urllib for parameters
memfile = io.BytesIO(mysock.read())
with ZipFile(memfile, 'r') as myzip:
    f = myzip.open('eggs.txt')
    content = f.read()  // or other file-like commands

check also Python in-memory zip library

Community
  • 1
  • 1
furins
  • 4,979
  • 1
  • 39
  • 57
  • 1
    I like this approach more than my answer. – Jon-Eric Jan 25 '13 at 17:38
  • :) but please be aware it's untested... I'm writing from my smartphone – furins Jan 25 '13 at 17:40
  • Now I tested it and it works. However your approach, Jon-Eric, is the correct one. So I edited my code: we must wrap the "mysock" content into a BytesIO object or ZipFile will complain about not being able to retrieve the filesize. – furins Jan 25 '13 at 18:00
4

The ftplib module allows downloading files via FTP.

The zipfile module allows extracting files from a zip file.

Here's the key, the io.BytesIO class allows you to pass in-memory bytes to anything that expects a file. (In Python 2.x, the StringIO module provides similar functionality.)

Jon-Eric
  • 16,977
  • 9
  • 65
  • 97
  • I know this is old. But this doesnt work for me. buf = io.BytesIO(str.encode("Test data to write")) buf = ZipFile.ZipFile(buf, mode='x') ftp.storbinary("STOR " + self.filename, buf) It throws me an error: KeyError: 'There is no item named 8192 in the archive' – elvainch Jul 16 '18 at 08:29
  • I provide more info here https://stackoverflow.com/questions/51358672/zip-and-ftp-a-string-on-the-fly-with-python – elvainch Jul 16 '18 at 09:33
0

The zipfile module can be used to extract things from a zip file; the ftplib would be used to access the zipfile. Unfortunately, ftplib doesn't provide a file-like object for zipfile to use to access the contents of the file. I suppose you could read the zip & store it in memory, for example in a string, which could then be wrapped up in a file-like object (StringIO), although you're still getting the whole zip, just not saving it to disk.

If you don't need to save the individual files, but just access (i.e. read) them, zipfile will allow you to do this.

Scott Hunter
  • 48,888
  • 12
  • 60
  • 101
0

I couldn't find a possible way to extract the files directly, but here is an alternative:

First, download the file from the FTP

ftp =ftplib.FTP(FtpServer)          #connect to the ftp server
ftp.login(ServerUser,ServerPwd)     #using your credentials here

filedata = open(os.path.join(destination,DowloadedFileName),'wb')
ftp.retrbinary('RETR '+SourceFilename,filedata.write)      
filedata.close()
ftp.quit()

Second, extract the files from the zip:

path_to_zip_file = os.path.join(destination,DowloadedFileName)
directory_to_extract_to = destination
with zipfile.ZipFile(path_to_zip_file, 'r') as zip_ref:
    zip_ref.extractall(directory_to_extract_to)
           

Lastly, remove the downloaded zip file

os.remove(path_to_zip_file)
AverageGod
  • 95
  • 1
  • 6