Ruby GPGME - 如何加密大文件
Ruby GPGME - How to encrypt large files
我在 Ruby 中使用 GPGME 加密大文件(大于可用内存)时遇到困难。
#!/usr/bin/ruby
require 'gpgme'
def gpgfile(localfile)
crypto = GPGME::Crypto.new
filebasename = File.basename(localfile)
filecripted = crypto.encrypt File.read(localfile), :recipients => "info@address.com", :always_trust => true
File.open("#{localfile}.gpg", 'w') { |file| file.write(filecripted) }
end
gpgpfile("/home/largefile.data")
在这种情况下,我得到了内存分配错误:
"read: failed to allocate memory (NoMemoryError)"
有人可以向我解释如何逐块读取源文件(例如 100Mb)并通过加密写入它们吗?
最明显的问题是您使用 File.read(localfile)
将整个文件读入内存。 Crypto#encrypt
方法将一个 IO 对象作为其输入,因此您可以将一个 File 对象传递给它,而不是 File.read(localfile)
(returns 文件的内容作为字符串)。同样,您可以将 IO 对象作为 :output
选项,让您将输出直接写入文件而不是内存中:
def gpgfile(localfile)
infile = File.open(localfile, 'r')
outfile = File.open("#{localfile}.gpg", 'w')
crypto = GPGME::Crypto.new
crypto.encrypt(infile, recipients: "info@address.com",
output: outfile,
always_trust: true)
ensure
infile.close
outfile.close
end
我从未使用过 ruby-gpgme,所以我不能 100% 确定这会解决您的问题,因为这在一定程度上取决于 ruby-gpgme 在幕后所做的事情,但来自文档我看过的来源似乎是 sanely-built gem 所以我猜这会成功。
我在 Ruby 中使用 GPGME 加密大文件(大于可用内存)时遇到困难。
#!/usr/bin/ruby
require 'gpgme'
def gpgfile(localfile)
crypto = GPGME::Crypto.new
filebasename = File.basename(localfile)
filecripted = crypto.encrypt File.read(localfile), :recipients => "info@address.com", :always_trust => true
File.open("#{localfile}.gpg", 'w') { |file| file.write(filecripted) }
end
gpgpfile("/home/largefile.data")
在这种情况下,我得到了内存分配错误: "read: failed to allocate memory (NoMemoryError)"
有人可以向我解释如何逐块读取源文件(例如 100Mb)并通过加密写入它们吗?
最明显的问题是您使用 File.read(localfile)
将整个文件读入内存。 Crypto#encrypt
方法将一个 IO 对象作为其输入,因此您可以将一个 File 对象传递给它,而不是 File.read(localfile)
(returns 文件的内容作为字符串)。同样,您可以将 IO 对象作为 :output
选项,让您将输出直接写入文件而不是内存中:
def gpgfile(localfile)
infile = File.open(localfile, 'r')
outfile = File.open("#{localfile}.gpg", 'w')
crypto = GPGME::Crypto.new
crypto.encrypt(infile, recipients: "info@address.com",
output: outfile,
always_trust: true)
ensure
infile.close
outfile.close
end
我从未使用过 ruby-gpgme,所以我不能 100% 确定这会解决您的问题,因为这在一定程度上取决于 ruby-gpgme 在幕后所做的事情,但来自文档我看过的来源似乎是 sanely-built gem 所以我猜这会成功。