如何使用Ruby的File.new将附件ZIP写入文件?

时间:2015-11-04 09:50:21

标签: ruby unzip

我正在连接到IMAP服务器并下载带有ZIP附件的邮件。我在本地计算机上和远程计算机上运行脚本。我能够在两台机器上正确保存文件,但由于某种原因,我在远程机器上解压缩时遇到错误。

保存zip附件的ruby代码:

attachment = imap.fetch(message_id, "BODY[2]")[0].attr["BODY[2]"]
save_path = "#{save_path_base}/#{fname}"
File.new(save_path, "wb+").write(attachment.unpack("m"))

在我的本地计算机(OS X)上运行unzip file.zip的文件工作正常,但在远程计算机(CentOS)上,同样的命令会产生错误:

找不到中心目录签名。这个文件不是 一个zip文件,或者它构成一个多部分存档的磁盘。在里面 后一种情况,将在上面找到中心目录和zipfile注释 该档案的最后一个磁盘。

什么原因导致文件在本地计算机上正确保存并在远程计算机上损坏?或者我的本地解压缩忽略错误?在两台计算机unzip上都指向/usr/bin/unzip

修改

在我的本地计算机上,file file.zip为我提供 Zip存档数据,至少提取v2.0。我的本地Ruby版本为ruby 1.8.7 (2012-02-08 patchlevel 358)

在我的远程服务器上,该命令返回 ASCII文本,行很长,没有行终止符。我的远程Ruby版本为ruby 2.0.0p647 (2015-08-18)

如何确保文件在远程计算机上被识别为ZIP?

编辑:以下添加的解决方案作为答案

1 个答案:

答案 0 :(得分:0)

当然,解决方案是弄清楚Ruby版本之间的变化。 In this thread有人指出:

  

1.8相当于调用join,在1.9中它等同于调用inspect。要在1.8和1.9中获得所需的行为,请拨打join而不是to_s

所以解决方法是将线路改为

File.new(save_path, "wb+").write(attachment.unpack("m").join)

因为默认write调用to_s,如果提供了字符串以外的内容。