Есть ли особая хитрость для загрузки zip-файла и записи его на диск с помощью Python? - PullRequest
1 голос
/ 23 февраля 2009

Я отправляю zip-файл по FTP с удаленного FTP-сайта, используя ftplib Python. Затем я пытаюсь записать его на диск. Запись в файл работает, однако большинство попыток открыть zip с помощью WinZip или WinRar не удаются; оба приложения утверждают, что файл поврежден. Как ни странно, если щелкнуть правой кнопкой мыши и попытаться извлечь файл с помощью WinRar, файл извлечет .

Итак, чтобы быть понятным, запись в файл будет работать, но не будет открывать внутри популярных zip-приложений, но будет распаковывать, используя те же приложения. Обратите внимание, что модуль zipfile Python никогда не может извлечь zip-файлы.

Вот код, который я использую для получения zip-файла с FTP-сайта (пожалуйста, игнорируйте плохие вкладки, это не проблема).

filedata = None
def appender(chunk):
    global filedata
    filedata += chunk


def getfile(filename):
  try:
      ftp = None

      try:
          ftp = FTP(address)
          ftp.login('user', 'password')

      except Exception, e:
          print e

      command = 'RETR ' + filename

      idx = filename.rfind('/')
      path = filename[0:idx]
      ftp.cwd(path)
      fileonly = filename[idx+1:len(filename)]

      ftp.retrbinary('RETR ' + filename, appender)

      global filedata
      data = filedata

      ftp.close()

      filedata = ''
      return data

  except Exception, e:
      print e

data = getfile('/archives/myfile.zip')    
file = open(pathtoNTFileShare, 'wb')
file.write(data)
file.close()

Ответы [ 2 ]

2 голосов
/ 23 февраля 2009

Передача file.write непосредственно внутри функции retrbinary вместо передачи appender. Это будет работать, и это также не будет использовать слишком много оперативной памяти при загрузке большого файла.

Если вы хотите, чтобы данные хранились внутри переменной, у вас также может быть переменная с именем:

blocks = []

Затем перейдите к retrbinary вместо appender:

blocks.append

Ваша текущая функция appender неверна. + = не будет работать правильно, когда есть двоичные данные, потому что он попытается выполнить добавление и остановку строки при первом NULL, который он увидит.

Как уже упоминалось @Lee B, вы также можете использовать urllib2 или Curl. Но ваш текущий код почти верен, если вы сделаете небольшие изменения, которые я упомянул выше.

1 голос
/ 23 февраля 2009

Я никогда не использовал эту библиотеку, но urllib2 работает нормально и более прост. Скручиваемость еще лучше.

Глядя на ваш код, я могу видеть пару вещей неправильно. При обнаружении исключения распечатывается только исключение, а затем продолжается. В случае фатальных ошибок, таких как отсутствие FTP-соединения, необходимо распечатать сообщение и выйти. Кроме того, ваши файловые данные начинаются как None, затем ваш аппендер использует + =, чтобы добавить к этому, поэтому вы пытаетесь добавить строку + None, которая выдает TypeError, когда я пытаюсь это сделать здесь. Я удивлен, что это работает вообще; Я бы догадался, что appender выдаст исключение, и поэтому FTP-копия будет прервана.

Во время перечитывания я только что заметил другой ответ об использовании + = для двоичных данных. Это вполне может быть; Python иногда пытается быть умным и может «помогать», когда вы соединяете строки с пробелами или NUL в них, или что-то в этом роде. Лучше всего, чтобы файл был открыт (давайте назовем его outfile), а ваш appender просто выберет outfile.write (chunk).

...