编写二进制文件时编码:: UndefinedConversionError

时间:2011-07-25 02:10:01

标签: ruby-on-rails ruby

我有一个网站需要加密和存储上传到服务器的二进制文件。上传和存储工作正常,但我在尝试编写加密文件时遇到此错误:

  

编码:: UndefinedConversionError(从ASCII-8BIT到UTF-8的“\ xDD”):

导致它的代码如下所示:

fd_in = IO.sysopen(self[:name].tempfile.path, "rb")                           
file_in = IO.open(fd_in)                                                      
fd_out = IO.sysopen(self[:name].tempfile.path + ".encrypted", "wb")           
file_out = IO.open(fd_out)                                                    
cipher = OpenSSL::Cipher::Cipher.new('aes-256-cbc')                           
cipher.encrypt                                                                                                         
cipher.key = cipher_key                                                     
cipher.iv = cipher_iv                                                       
while chunk = file_in.read(1024)                                              
  file_out << cipher.update(chunk)                                            
end
file_out << cipher.final

导致错误的行是file_out&lt;&lt; while循环中的cipher.update(chunk)。我在网上查了一下,发现了一些类似ASCII / UTF转换问题的报告,但它们似乎都是基于强制字符串输入,而不是流文件输入。我正在使用Ruby 1.9.2,我认为它会影响默认的字符串编码。

我的理由为什么(我认为)我需要使用基于流的方法:文件往往很大,我不想将整个文件(输入或输出)加载到内存中来处理它。 / p>

感谢任何帮助。谢谢。

1 个答案:

答案 0 :(得分:30)

当en- / decrypting将输入和输出视为原始字节时,您想要做什么,您希望避免因不惜一切代价将编码与数据相关联而导致的任何转码。因此,您应该以二进制模式打开文件,包括读取和写入。

实际上你是这样做的,但使用IO #sysopen,但是在使用IO#open时你没有传递“b”标志。

如果您尝试这样做,您的代码应该有效:

fin = File.open("TODO", "rb")                           
fout = File.open("TODO.encrypted", "wb")           
cipher = OpenSSL::Cipher::Cipher.new('aes-256-cbc')
cipher.encrypt                     
cipher.key = key                                                     
cipher.iv = iv                                                       
while chunk = fin.read(1024)                                              
  fout << cipher.update(chunk)                                            
end
fout << cipher.final
fin.close
fout.close