1

我正在使用 Python 的 ftplib 从远程 FTP 站点上传一个 zip 文件。然后我尝试将其写入磁盘。文件写入有效,但是大多数使用 WinZip 或 WinRar 打开 zip 的尝试都失败了;两个应用程序都声称文件已损坏。然而奇怪的是,当右键单击并尝试使用 WinRar 提取文件时,文件被提取。

所以需要明确的是,文件写入将起作用,但不会在流行的 zip 应用程序中打开,但使用这些相同的应用程序解压缩。请注意,Python zipfile 模块永远不会无法提取 zip。

这是我用来从 FTP 站点获取 zip 文件的代码(请忽略错误的标签,这不是问题)。

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()
4

2 回答 2

2

直接在 retrbinary 函数内部传递 file.write 而不是传递 appender。这将起作用,并且在您下载大文件时也不会使用那么多 RAM。

但是,如果您希望将数据存储在变量中,您还可以有一个名为:

blocks = []

然后传递给 retrbinary 而不是 appender:

blocks.append

您当前的 appender 函数是错误的。+= 在存在二进制数据时将无法正常工作,因为它会尝试执行字符串追加并在它看到的第一个 NULL 处停止。

正如@Lee B 所提到的,您还可以使用 urllib2 或 Curl。但是,如果您进行我上面提到的小修改,那么您当前的代码几乎是正确的。

于 2009-02-23T01:13:59.353 回答
1

我从未使用过该库,但 urllib2 工作正常,而且更简单。卷曲更好。

查看您的代码,我可以看到一些错误的地方。您的异常捕获仅打印异常,然后继续。对于像没有获得 FTP 连接这样的致命错误,他们需要打印消息然后退出。此外,您的文件数据以 None 开始,然后您的 appender 使用 += 添加到该文件,因此您尝试附加一个字符串 + None,当我在这里尝试时它会给出 TypeError。我很惊讶它的工作原理。我猜到 appender 会抛出异常,因此 FTP 副本会中止。

在重新阅读时,我刚刚注意到另一个关于在二进制数据上使用 += 的答案。很可能就是这样;python 有时会尝试变得聪明,当你加入带有空格或 NUL 的字符串或类似的东西时,它可能会“提供帮助”。最好的办法是打开文件(我们称它为 outfile),然后使用 appender 来处理 outfile.write(chunk)。

于 2009-02-23T01:12:00.437 回答