下载并写入.tar.gz文件时避免损坏。

5
如何使用Ruby下载文件,特别是.zip和.tar.gz格式的文件,并将它们写入磁盘? 该问题最初与MacRuby中的一个错误有关,但答案适用于上述一般问题。 使用MacRuby,我发现该文件的大小似乎与参考文件相同,但存档文件无法提取。我现在正在尝试的是:https://gist.github.com/arbales/8203385 谢谢!

大小并不重要。你唯一能找出错误的方法就是查看内容。我建议使用一个简单重复模式的小测试文件进行调试。 - Azeem.Butt
如果我在TextMate中打开这些文件,它们看起来是一样的... - arbales
2
你尝试过使用open-uri吗? - Benjamin Oakes
filePath:path 语法是什么意思?我以前没见过。 - Geo
@Geo,这是Ruby 1.9.1的命名参数语法 — 我正在编写一个MacRuby应用程序,因此可以使用本地Cocoa小部件。 - arbales
真的是一个非常简单的问题:文件的校验和(如md5sum或类似)是否相同?您可以使用类似xdelta的工具来查看文件之间的差异吗? - Stobor
4个回答

13

我已经成功使用这段代码下载并解压GZip文件:

require 'open-uri'
require 'zlib'

open('tarball.tar', 'w') do |local_file|
  open('http://github.com/jashkenas/coffee-script/tarball/master/tarball.tar.gz') do |remote_file|
    local_file.write(Zlib::GzipReader.new(remote_file).read)
  end
end

.tar.gz 文件似乎无法工作。"mrb[2877:a0f] 不是 gzip 格式"。 - arbales
4
我修改了代码,加入了你示例中的URL,并且在Ruby 1.8.7、1.9.1、Rubinius 1.0.0 RC2和JRuby 1.4.0中成功运行。然而,在MacRuby 0.5中运行时会保存一个乱码文件。我不知道原因,但这明显是MacRuby中的一个bug。 - Theo
2
我也尝试使用HTTParty重写代码,但结果相同(但HTTParty可能使用与open-uri相同的机制,所以这并不奇怪)。 - Theo
我担心这是MacRuby的错误。现在我必须想出一些奇怪的多步Cocoa方法来下载。 - arbales
我使用以下代码传递了用户名和密码进行基本的HTTP身份验证:"open(uri, :http_basic_authentication=>[@username, @password])"。 - Sumit Munot
显示剩余4条评论

3

这是一个不错的简单解决方案,我已经尝试了open-uri,但依然得到了一个损坏的文件。 - arbales
奇怪。我目前正在使用这个系统,它可以下载所有国家医学图书馆的zip文件(使用resque并行下载),由700多个文件组成,每个文件都有数十MB。我会从shell中使用curl或wget获取它们,并确保存档没有根本性问题。 - user253455
当我使用Curl、wget或Safari下载这些文件时,它们可以正常解压缩,但是当我在我的应用程序中尝试解压缩时,这些文件就会拒绝解压缩——它们经常会创建一些空的.cpg或其他文件。 - arbales
使用这种简单方法后,我最终不得不在open()调用中添加一个头部 {'Accept-encoding' => ''},因为.tar.gz下载在下载过程中被错误地解压缩(就像Web服务器发送的gzip编码)。 - Michael Berkowski
也就是说,我保存到磁盘的文件是未压缩的 .tar 文件,而不是预期的原始 .tar.gz 文件。 - Michael Berkowski

1

我最后一次在使用Ruby时遇到损坏的文件是因为我忘记在File.open之后立即调用file.binmode。花了我数小时才找出问题所在。它对您的问题有帮助吗?


谢谢,但文档说明这只在MSDOS中有用,我正在运行Mac OS,所以不应该有问题。 - arbales

0

当使用简单的open()调用通过open-uri下载.tar.gz文件时,我也遇到了在磁盘上解压缩文件时出现错误的问题。最终我发现文件大小比预期要大得多。

检查磁盘上的download.tar.gz文件,实际上它包含的是未压缩的download.tar文件;可以对其进行解压缩。这似乎是由于open()调用中隐含的Accept-encoding: gzip头部引起的,这在获取gzipped tarball时并不是我想要的。我能够通过在远程open()的可选哈希参数中发送一个空白的Accept-encoding头部来解决这个问题并打败这种行为:

open('/local/path/to/download.tar.gz', 'wb') do |file|
  # Send a blank Accept-encoding header
  file.write open('https://example.com/remote.tar.gz', {'Accept-encoding'=>''}).read
end

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接