Existe um truque especial para o download de um arquivo zip e escrevê-lo para o disco com Python?

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

  •  05-09-2019
  •  | 
  •  

Pergunta

Estou FTPing um arquivo zip a partir de um site FTP remoto usando ftplib do Python. Eu, então, tentar escrevê-lo em disco. Os trabalhos de gravação de arquivos, no entanto a maioria das tentativas de abrir o zip usando o WinZip ou WinRar falhar; Ambos os aplicativos reivindicar o arquivo está corrompido. Estranhamente no entanto, quando o botão direito e tentar extrair o arquivo usando o WinRAR, o arquivo irá extrato.

Assim, para ser claro, a gravação de arquivos vai funcionar, mas não irá open dentro dos aplicativos zip populares, mas irá descomprimir usando os mesmos aplicativos. Note que o Python zipfile módulo não não consegue extrair os fechos.

Aqui está o código que estou usando para obter o arquivo zip do site FTP (por favor ignore o mau tabulação, que não é o problema).

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()
Foi útil?

Solução

Passe file.write diretamente dentro da função retrbinary em vez de passar appender. Isto irá funcionar e ele também não vai usar tanta RAM quando você está baixando um arquivo grande.

Se você gostaria dos dados armazenados dentro de uma variável, porém, você também pode ter uma variável chamada:

blocks = []

Em seguida, passe para retrbinary vez de appender:

blocks.append

A sua função appender atual é errado. + = Não irá funcionar corretamente quando há dados binários, porque ele vai tentar fazer um acréscimo corda e parar no primeiro NULL que vê.

Como mencionado por @Lee B você também pode usar urllib2 ou dobras. Mas o seu código atual é quase correta se você fizer as pequenas modificações que eu mencionei acima.

Outras dicas

Eu nunca usei essa biblioteca, mas urllib2 funciona bem, e é mais simples. Onda é ainda melhor.

Olhando para o código, eu posso ver um par de coisas erradas. Seu exceção captura só imprime a exceção, em seguida, continua. Para erros fatais como não conseguir uma conexão FTP, eles precisam imprimir a mensagem e depois sair. Além disso, o filedata começa como Nenhum, em seguida, seus usos Appender + = para adicionar a isso, então você está tentando anexar uma string + Nenhum, o que dá uma TypeError quando eu experimentá-lo aqui. Eu estou surpreso que é trabalhar em tudo; Eu teria imaginado que o appender iria lançar uma exceção, e assim a cópia FTP iria abortar.

Enquanto re-leitura, eu só notei outra resposta sobre o uso de + = em dados binário. Isso poderia muito bem ser ele; tentativas python para ser por vezes inteligentes, e poderia ser "ajudar" quando você se juntar cordas com espaços em branco ou NULs neles, ou algo parecido. Sua melhor aposta não é ter o arquivo aberto (vamos chamá-lo outfile), e usar o seu appender apenas outfile.write (pedaço).

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top