为啥我会收到从 ASCII-8BIT 到 UTF-8 的字符串编码问题“\xE2”?

Posted

技术标签:

【中文标题】为啥我会收到从 ASCII-8BIT 到 UTF-8 的字符串编码问题“\\xE2”?【英文标题】:Why do I get a string encoding issue "\xE2" from ASCII-8BIT to UTF-8?为什么我会收到从 ASCII-8BIT 到 UTF-8 的字符串编码问题“\xE2”? 【发布时间】:2013-06-22 10:20:48 【问题描述】:

我正在尝试从电子邮件下载 PDF 并将内容写入文件。出于某种原因,我收到此错误:

An Encoding::UndefinedConversionError occurred in attachments#inbound: "\xE2" from ASCII-8BIT to UTF-8 app/controllers/api/attachments_controller.rb:70:in `write'

这是我的代码:

def inbound
    if Rails.env.production? or Rails.env.staging?
      email = Postmark::Mitt.new(request.body.read)
    else
      email = Postmark::Mitt.new(File.binread "#Rails.root/app/temp_pdfs/email.json")
    end

    if email.attachments.count == 0
      # notify aidin that we got an inbound email with no attachments
      respond_to do |format|
        format.json  head :no_content 
      end
      return
    end
    attachment = email.attachments.first
    filename = "attachment" + (Time.now.strftime("%Y%m%d%H%M%S")+(rand * 1000000).round.to_s) + ".pdf"
    base_path = "#Rails.root/temp_attachments/"
    unless File.directory?(base_path)
      Dir::mkdir(base_path)
    end
    file = File.new base_path + filename, 'w+'
    file.write Base64.decode64(attachment.source['Content'].encode("UTF-16BE", :invalid=>:replace, :replace=>"?").encode("UTF-8"))
    file.close
    write_options = write_options()
    write_options[:metadata] = :filename => attachment.file_name, :content_type => attachment.content_type, :size => attachment.size 

    obj = s3_object()
    file = File.open file.path
    obj.write(file.read, write_options)
    file.close

    FaxAttach.trigger obj.key.split('/').last

    render :nothing => true, :status => 202 and return
  end

我看了一圈,看起来解决这个问题的方法是:

file.write Base64.decode64(attachment.source['Content'].encode("UTF-16BE", :invalid=>:replace, :replace=>"?").encode("UTF-8"))

但它似乎不起作用。

【问题讨论】:

能否添加转换失败的数据摘录,出现问题\xE2(错误消息在技术上是正确的,ASCII-8BIT 中没有与\xE2 关联的字符)?我最好的猜测是,在 Ruby 知道如何处理该字符之前,您需要强制对已读取的数据进行编码 - 可能类似于 .force_encoding("ISO-8859-1")。当然,如果你强制编码,你可能会选择错误,所以可能值得找出 PDF 中的字符是什么。 @NeilSlater 当然,给我两秒钟。都是base 64编码的,所以我会解码并发布输出 @NeilSlater 实际上,当我基于 64 解码时,它给了我一堆乱码。 gist.github.com/chintanparikh/5859337 我没有正确阅读您的整个问题,只关注错误消息。我是否认为您想要保存作为电子邮件附件发送的二进制文件?如果是这样,则不需要管理字符编码,如果更改编码,几乎肯定会损坏文件。 您使用的是哪个电子邮件处理 gem? 【参考方案1】:

错误消息实际上是在文件写入时抛出的,而不是通过参数内的编码/解码,因为 Ruby 正在尝试在 file.write 上应用默认字符编码。为了防止这种情况,最快的解决方法是在打开文件时添加b 标志

file = File.new base_path + filename, 'wb+'
file.write Base64.decode64( attachment.source['Content'] )

假设传入的附件是用 Base64 编码的,正如您的代码所暗示的那样(我无法验证这一点)。存储在attachment.source['Content'] 中的 Base64 编码在 ASCII-8BIT 和 UTF-8 中应该是相同的字节,因此在对 decode64 的调用中将其转换是没有意义的。

【讨论】:

不再出错,但也不起作用。不过,这可能是该过程中的另一个步骤,因此我将其标记为已解决。干杯!

以上是关于为啥我会收到从 ASCII-8BIT 到 UTF-8 的字符串编码问题“\xE2”?的主要内容,如果未能解决你的问题,请参考以下文章

mysql2 gem 0.3.15 提供编码设置为“utf8”的 ASCII-8BIT

ruby `encode': "\xC3" 从 ASCII-8BIT 到 UTF-8 (Encoding::UndefinedConversionError)

将非 ASCII 字符从 ASCII-8BIT 转换为 UTF-8

为啥我会收到涉及 `_kFIRLoggerInstanceID` 的错误?

为啥我会收到此 GRPCProvider UpgradeResourceState terraform 错误?

不知道为啥我会收到 NullPointerException [重复]