我的一个邮件程序中有一行代码,用于添加包含用户姓氏和 DoB 的附件。 File.read
方法中有时会出现类型错误“没有将 StringIO 隐式转换为 String”。
attachments["#{@user.last_name.downcase}-#{@user.date_of_birth.strftime('%d%m%y')}.jpeg"] = File.read(URI.parse(@user.profile_picture_url).open)
它在大多数情况下都有效,但偶尔会因此错误而失败。我正在使用 Carrierwave 将文件上传到远程 S3 存储桶(如果这有影响的话)。
编辑:
我在控制台中进行了一些挖掘,坦白说这让我更加困惑!我有两个用户记录,都包含通过 Carrierwave 上传到 S3 的个人资料图片。如果我只是隔离 File.read
方法并使用两条记录进行尝试,则一个有效,另一个无效。检查 URI,它们看起来几乎相同。
但是,我发现Carrierwave支持读取文件的快捷方式,这解决了这个问题。这是更新后的代码:
attachments["#{@user.last_name.downcase}-#{@user.date_of_birth.strftime('%d%m%y')}.jpeg"] = @user.profile_picture.read
最佳答案
任何小于10kb
的内容都会以StringIO
而不是File
的形式打开。在文档中找不到实际的引用,所以这里是来源:
StringMax = 10240
def <<(str)
@io << str
@size += str.length
# NOTE: once you pass 10kb mark, you get a tempfile.
# v
if StringIO === @io && StringMax < @size
require 'tempfile'
io = Tempfile.new('open-uri')
io.binmode
Meta.init io, @io if Meta === @io
io << @io.string
@io = io
end
end
https://github.com/ruby/ruby/blob/v3_2_0/lib/open-uri.rb#L398
让我们测试一下:
>> require "open-uri"
>> File.write("public/small.txt", "a"*10240)
=> 10240
>> URI.open("http://localhost:3000/small.txt").class
=> StringIO
>> File.write("public/large.txt", "a"*(10240+1))
=> 10241
>> URI.open("http://localhost:3000/large.txt").class
=> Tempfile
您可以File.read
Tempfile
,但不能File.read
StringIO
。
修复方法是在 URI 上调用 read
:
>> URI.parse("http://localhost:3000/small.txt").read.class
=> String
>> URI.parse("http://localhost:3000/large.txt").read.class
=> String
# also works
>> URI.open("http://localhost:3000/small.txt").read.class
=> String
关于ruby-on-rails - 为什么有时会出现类型错误 "no implicit conversion of StringIO into String"? ruby /Rails,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/74992160/