Y at-il une astuce pour télécharger un fichier zip et l'écriture sur disque avec Python?

StackOverflow https://stackoverflow.com/questions/576238

  •  05-09-2019
  •  | 
  •  

Question

Je FTPing un fichier zip à partir d'un site FTP distant en utilisant la ftplib Python. J'essaiera également d'écrire sur disque. Les travaux d'écriture de fichiers, mais la plupart des tentatives d'ouvrir le zip en utilisant WinZip ou WinRar échouent; les deux applications affirment que le fichier est corrompu. Bizarrement cependant, quand un clic droit et en essayant d'extraire le fichier en utilisant Winrar, le fichier extrait.

Donc, pour être clair, l'écriture de fichiers fonctionnera, mais ne sera pas open à l'intérieur des applications zip populaires, mais décomprimer en utilisant ces mêmes applications. Notez que le module Python zipfile jamais n'extraire les fermetures éclair.

Voici le code que j'utilise pour obtenir le fichier zip à partir du site FTP (s'il vous plaît ignorer la mauvaise tabbing, ce n'est pas la question).

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()
Était-ce utile?

La solution

Passe file.write directement à l'intérieur de la fonction retrbinary au lieu de passer appender. Cela fonctionne et il sera également pas utiliser beaucoup de RAM lorsque vous téléchargez un fichier volumineux.

Si vous souhaitez les données stockées dans une variable si, vous pouvez aussi avoir une variable nommée:

blocks = []

Passez ensuite à retrbinary au lieu de appender:

blocks.append

Votre fonction actuelle appender est erroné. + = Ne fonctionnera pas correctement quand il y a des données binaires, car il va essayer de faire une append à cordes et arrêter au premier NULL qu'il voit.

Comme mentionné par @Lee B vous pouvez également utiliser urllib2 ou Curl. Mais votre code actuel est presque correct si vous faites les petites modifications que j'ai mentionnées ci-dessus.

Autres conseils

Je ne l'ai jamais utilisé cette bibliothèque, mais urllib2 fonctionne très bien et est plus simple. Curl est encore mieux.

En regardant votre code, je peux voir quelques mauvaises choses. Votre exception attrapant n'imprime l'exception, puis continue. Pour des erreurs fatales comme ne pas obtenir une connexion FTP, ils ont besoin d'imprimer le message, puis la sortie. En outre, votre filedata commence comme Aucun, votre appender utilise + = pour ajouter à cela, si vous essayez d'ajouter une chaîne + Aucun, ce qui donne une TypeError lorsque je tente ici. Je suis surpris que ça fonctionne du tout; Je l'aurais deviné que le appender jetterait une exception, et si la copie FTP serait abandonner.

en relisant, je viens de remarquer une autre réponse sur l'utilisation de + = sur des données binaires. Cela pourrait bien que ce soit; python essaie d'être intelligent parfois, et pourrait être « aide » lorsque vous rejoignez des chaînes avec des espaces ou NUL en eux, ou quelque chose comme ça. Votre meilleur pari il est d'avoir le fichier ouvert (appelons-le outfile), et utilisez votre appender juste outfile.write (morceau).

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top