为啥我在 rails 2 中使用 vpim 出现编码错误?

Posted

技术标签:

【中文标题】为啥我在 rails 2 中使用 vpim 出现编码错误?【英文标题】:Why am I getting an encoding error with vpim in rails 2?为什么我在 rails 2 中使用 vpim 出现编码错误? 【发布时间】:2011-09-09 18:11:47 【问题描述】:

我收到以下错误:

Vpim::InvalidEncodingError (email@email.net):
2011-06-07T01:37:06+00:00 app[web.1]:   .bundle/gems/ruby/1.8/gems/vpim-0.695/lib/vpim/field.rb:110:in `decode0'

它适用于其他电子名片。而且数据看起来很正确——应该是一封电子邮件:

这是一个示例 vcard,当有一封电子邮件时它会爆炸……我所做的修复它是手动删除第二封电子邮件,但这很痛苦:

BEGIN:VCARD
VERSION:2.1
N:Roberts;Paul;;;
FN:Paul Roberts
ORG:Sonoma Technology Inc
TITLE:EVP Business Dev/Chief Scientific Officer
TEL;WORK;VOICE:707-665-9900
TEL;WORK;FAX:707-665-9800
ADR;WORK;ENCODING=QUOTED-PRINTABLE:;;1455 N McDowell Blvd Suite D;Petaluma;CA;94954;USA
LABEL;WORK;ENCODING=QUOTED-PRINTABLE:1455 N McDowell Blvd Suite D=0D=0APetaluma, CA 94954=0D=0AUSA
URL:http://www.sonomatech.com
URL:http://www.sonomatech.com
EMAIL;PREF;INTERNET:paul@sonomatech.com
paul@sonomatech.com
NOTE;ENCODING=QUOTED-PRINTABLE:=0D=0A Data provided by Lead411,  http://www.lead411.com/=0D=0A =0D=0A
END:VCARD

这是我使用回形针和 vpim 的控制器:

 68      unless @contact.vcard.path.blank?
 69 
 70        paperclip_vcard = File.new(@contact.vcard.path)
 71 
 72       # try to scrub the vcard
 73        scrub_vcf(paperclip_vcard)
 74 
 75        @vcard = Vpim::Vcard.decode(paperclip_vcard).first
 76        @contact.title = @vcard.title
 77        @contact.email = @vcard.email
 78        @contact.first_name = @vcard.name.given
 79        @contact.last_name = @vcard.name.family
 80        @contact.phone = @vcard.telephones[0]
 81        @contact.fax = @vcard.telephones[1]
 82 
 83        @contact.address.street1 = @vcard.address.street
 84        @contact.address.city = @vcard.address.locality
 85        @contact.address.state = @vcard.address.region
 86        @contact.address.zip = @vcard.address.postalcode
 87        @contact.company_name = @vcard.org.fetch(0)
 88 
 89     end

【问题讨论】:

【参考方案1】:

您需要查看您的 Vcard 是如何创建的;第 14 行的第二封电子邮件不是有效的属性定义,这就是导致解析器出错的原因(这就是如果您手动删除它,它会成功解析的原因)。

您可以在the Vcard 2.1 specification 的第 2 节中阅读有关属性定义的信息(RTF 版本——可读性更高——在here 可用)。

根据您提供的信息,这似乎不是Vpim 在解码方面的问题,而是您的 Vcard 是如何创建的。如果您自己创建 Vcard,我会看看您的编码逻辑。如果您从外部来源接收它们,那么您可能需要编写一些自定义清理逻辑来摆脱不正确的属性定义,这样您就不必自己手动删除它们。

您应该能够通过对每一行进行快速正则表达式检查来轻松完成此操作:

def scrub_vcf(vcard)
  line_arr = File.readlines(vcard)
  line_arr.delete_if  |line| line.match(/^.+\:.+$/).nil? 
  File.open(vcard, "w") do |f| 
    line_arr.each|line| f.puts(line)
  end
end
# use the scrubbed vcf with vpim

当然,将其保存在数组中可能比将其写回文件更快,仅供参考。

希望对您有所帮助。


更新:如果你不想保留文件,你可以返回一个字符串,Vpim can decode 而不是文件:

def scrub_vcf(vcard)
  line_arr = File.readlines(vcard)
  line_arr.delete_if  |line| line.match(/^.+\:.+$/).nil? 
  return line_arr.join
end
# use the scrubbed vcf with vpim #=> Vpim::Vcard.decode(scrub_vcf(vcard))

请注意,在运行 ruby​​ 1.9.x 时,我在使用带有 Vpim::Vcard.decode 的字符串时遇到了问题,因为 String 类不再具有 each 方法。不过,Ruby 1.8.7 可以正常工作。 Vpim 看起来自 2008/2009 年以来没有升级,所以它可能没有升级为与 ruby​​ 1.9.x 一起使用。


再次更新:这是为 ruby​​ 1.9.x 使用而更新的 Vpim 版本(正好修复了我之前遇到的问题):https://github.com/sam-github/vpim

【讨论】:

@neezer,这应该仍然可以将它写回heroku上的文件,对吧?我应该把这个方法放在哪里,在我用 vpim 处理 vcf 的控制器中? @Angela 这取决于您是否要保留一份已清理的 vcard 以供以后使用。如果是这样,那么您可以使用Amazon S3 来存储副本,因为 Heroku 的文件系统是只读的。如果以后不需要它,只需将数组写回字符串,然后在字符串上使用 vpim。 @Angela 至于把它放在哪里,这又取决于你用你的代码做什么。惯例是“胖模型,瘦控制器”,所以如果您将这些 vcard 导入数据库,您可能需要考虑将其放入您的模型中——也许在 before_save 回调中——以保持控制器精简和平均。 @neezzer,谢谢——您的代码写入文件,而不是字符串,对吧?我不需要保留擦洗的电子名片....如果没有“:”字符,基本上这会擦洗它? @neezer,是的...更愿意把它放在模型中,现在我的控制器很胖,以后会重构,但只是想在短期内得到这个补丁——我把它作为一个控制器方法但出现错误,我会发布我的代码,也许你可以建议?

以上是关于为啥我在 rails 2 中使用 vpim 出现编码错误?的主要内容,如果未能解决你的问题,请参考以下文章

为啥我在 Rails 应用程序中使用 force_ssl 获得无限重定向循环?

为啥我的实例变量在我的 Rails 视图中总是 Nil

为啥 Heroku 使用服务器时间而不是 Rails 时区进行日志记录?

Rails4:为啥 resque 工人不找工作

为啥 Rails 渲染视图如此缓慢?

为啥我在使用 PL/SQL 的 Oauth 2 访问令牌代码中出现此错误?