通过Paperclip 4连接时,在S3中设置内容类型?

时间:2014-04-17 04:40:56

标签: ruby-on-rails-3 csv amazon-s3 paperclip

我尝试使用paperclip 4.1.1将CSV文件附加到Rails3模型,但我无法将S3报告的内容类型设为text/csv(相反,我我得到了text/plain)。当我随后从S3下载文件时,扩展名将更改为与内容类型匹配,而不是保留原始扩展名(因此test.csv将作为test.txt下载)。

从我所看到的,当您上传文件时,FileAdapter将使用ContentTypeDetector(调用file -b --mime filename)确定的任何值来缓存创建时的内容类型。不幸的是,CSV文件返回text/plain这是有道理的,你怎么能真正区分它?尝试使用attachment.instance_write(:content_type, 'text/csv')设置内容类型仅设置模型中的值,不会影响写入S3的内容。

FileAdapter的content_type在此处初始化:https://github.com/thoughtbot/paperclip/blob/v4.0/lib/paperclip/io_adapters/file_adapter.rb#L14

创建io_adapter的调用: https://github.com/thoughtbot/paperclip/blob/v4.0/lib/paperclip/attachment.rb#L98

我确实在这里进行了通用上传(因此我无法对has_attached_file中的S3标头定义中的内容类型进行硬编码),而且我并不真正想要内容类型欺骗保护。有什么想法/建议吗?我宁愿不降级到3.5,因为这只会拖延痛苦,但如果这是唯一的方式,我会接受它......

2 个答案:

答案 0 :(得分:9)

如果您使用的是fog,那么您可以执行以下操作:

has_attached_file :report,
  fog_file: lambda { |attachment|
    {
      content_type: 'text/csv',
      content_disposition: "attachment; filename=#{attachment.original_filename}",
    }
  }

如果您使用Amazon S3作为存储提供商,那么这样的事情应该有效:

has_attached_file :report
  s3_headers: lambda { |attachment|
    { 
      'Content-Type' => 'text/csv',
      'Content-Disposition' => "attachment; filename=#{attachment.original_filename}",
    }
  }

答案 1 :(得分:0)

最近遇到了这个问题,后期处理和 lambda 都不起作用,所以做了一个变通办法。与其他观察相同,调用 s3 lambda 标头时附件的值为空。

  1. 将此行添加到模型中
attr_accessor :tmp_content_type, :tmp_file_name
  1. 覆盖文件分配方法,以便我们可以获取文件信息并将其存储以备后用
 def file=(f)
  set_tmp_values(f.path)
  file.assign(f)
end

def set_tmp_values(file_path)
  self.tmp_file_name = File.basename(file_path)
  self.tmp_content_type = MIME::Types.type_for(file_path).first.content_type
end
  1. 使用临时变量
:s3_headers => lambda { |attachment|
  {
    'Content-Type' => attachment.tmp_content_type,
    "Content-Disposition" => "attachment; filename=\"# {attachment.tmp_file_name}\""
  }
}