Rails ActiveRecord UTF-8问题中的无效字节序列

时间:2012-05-13 10:02:28

标签: ruby-on-rails ruby-on-rails-3 activerecord

我正在使用MSSQL 2005.

我的 StringIO 对象包含 zip 文件内容。

以下是我获取zip二进制数据的方法:

    stringio = Zip::ZipOutputStream::write_buffer do |zio|
        Eclaim.find_by_sql("SET TEXTSIZE 67108864")
        zio.put_next_entry("application.xml")
        #zio.write @claim_db[:xml]
        biblio = Nokogiri::XML('<?xml version="1.0" encoding="utf-8"?>' + @claim_db[:xml], &:noblanks)
        zio.write biblio.to_xml

        builder = Nokogiri::XML::Builder.new(:encoding => 'utf-8') do |xml|
            xml.documents {
                docs.where("ext not in (#{PROHIBITED_EXTS.collect{|v| "'#{v}'"}.join(', ')})").each{|doc|
                    zio.put_next_entry("#{doc[:materialtitle_id]}.#{doc[:ext]}")
                    zio.write doc[:efile]

                    xml.document(:id => doc[:materialtitle_id]) {
                        xml.title doc[:title]
                        xml.code doc[:code]
                        xml.filename "#{doc[:materialtitle_id]}.#{doc[:ext]}"
                        xml.extname doc[:ext]
                    }

                }
            }
        end

        zio.put_next_entry("docs.xml")
        zio.write builder.to_xml
    end

    stringio

在我的控制器中,我尝试:

data.rewind
@claim.docs.create(
    :title => 'Some file',
    :ext => 'zip',
    :size => data.length,
    :receive_date => Time.now,
    :efile => data.sysread
)

但是Rails在UTF-8

中抱怨无效的字节序列

请帮助我。

3 个答案:

答案 0 :(得分:6)

如果流配置为UTF-8流,则无法编写压缩二进制文件(可能包含任何值)。

我认为,在写入之前将data设置为二进制流:

data.force_encoding "ASCII-8BIT"

可能有帮助。

答案 1 :(得分:1)

什么是抱怨,ruby,ActiveRecord或SQL Server?我的猜测是SQL Server。确保数据库中efile字段的数据类型是二进制BLOB。

答案 2 :(得分:1)

您应该在构成部分中解决问题并对较小的单元进行故障排除。消除复杂性,直到找到问题的根源。例如,您是否尝试使用控制台中的属性来执行简单的Document.create,以消除控制器代码可能出错的可能性?像Document.create :efile => File.read('sometiny.zip')之类的东西,就是从那里开始的。

假设有效或中断,您可以获得更简单的支持请求,并且发出噪音更少。现在我怀疑你的控制器代码,而不是SQL Server适配器或连接模式,因为我已经测试了hilt的简单二进制数据。假设上述方法不起作用,您可以继续检查较小的组件。

例如,efile列的数据类型是什么?在控制台中执行此操作,找出Document.columns_hash['efile']并查看@sql_type。它是否适合varbinary(max)

从那里开始,你使用什么连接模式与SQL Server适配器,TinyTDS?默认情况下,TinyTDS会根据需要将所有内容转换为UTF8,并且非常聪明。我已经测试了从二进制到许多不同编码的所有内容。顺便说一下,如果你使用的是TinyTDS,你是否确保使用libiconv编译了FreeTDS,以便它可以正确地完成所有这些操作?假设您的路径中有FreeTDS的二进制文件,则可以通过在控制台tsql -C中执行以下操作轻松进行检查。这应输出几行,查找“iconv library:yes”。还要确保你的运行速度为0.91或更高!

最后,有一点建议,SET TEXTSIZE在那里是错误的。您只希望每个连接执行一次。见https://github.com/rails-sqlserver/activerecord-sqlserver-adapter#configure-connection--app-name