将现有的S3文件链接作为Paperclip附件

10

我有一个外部服务,它创建文件并将它们存储到S3(我的Rails应用程序可以访问)。

我希望能够使用Paperclip来存储S3对象以及其缩略图。我找不到如何将Paperclip与已经在S3上的文件一起使用的文档。因此,我的代码应该如下所示:

page = Page.find(3)
page.s3_url = s3_url # I have the s3 route. And I would need to generate a thumbnail too.
page.save

换句话说:

我该如何告诉PaperClip我的附件已经在S3中了?

编辑:

以下是我目前的代码:

我知道已经上传到S3中的文件的文件名、内容长度和内容类型。所以,既然关联是一个页面 has_attached_file::screenshot

我这样做:

@page = Page.find(3)
@page.update_attributes(screenshot_content_type: screenshot_content_type, screenshot_file_size: screenshot_file_size, screenshot_update_at: screenshot_updated_at, screenshot_file_name: screenshot_file_name)

所以,现在我可以执行:

@page.screenshot,然后我可以看到图钉对象。 但是,当我执行:

@page.screenshot.url => URL并不是我最初存储图像的那个URL。

2个回答

7
我已经通过 paperclip插值 解决了这个问题:
  1. 在您的模型中定义一个字段,该字段将存储上传文件的路径
  2. 通过属性更新将 paperclip 附件信息加载到数据库中
  3. 使用插值指定 paperclip 附件 :path,因此它首先查找上传的文件,然后查找默认文件
  4. 获利!
这将起到作用,因为 S3 存储如何组合 URL

路径:这是文件将存储在其中的 bucket 下的键。 URL 将从 bucket 和路径构建。这是您要插值的内容。键应该是唯一的,就像文件名一样,尽管 S3(严格来说)不支持目录,但您仍然可以使用 / 来分隔文件名的部分。

以下是更多详细信息和代码: 模型
class MyModel
    has_attached_file :file, path: ":existent_file_or_default", storage: :s3
end

文件上传Gem Paperclip的插值

将此代码放置于config/initializers目录下

Paperclip.interpolates :existent_file_or_default do |attachment, style|
  attachment.instance.existent_file_path ||
    attachment.interpolator.interpolate(":class/:attachment/:id_partition/:style/:filename", attachment, style)
end

附加现有项目

MyModel.create({
  existent_file_path: "http://your-aws-region.amazonaws.com/your-bucket/path/to/existent/file.jpeg",
  file_file_name: "some_pretty_file_name.jpeg",
  file_content_type: "image/jpeg",
  file_file_size: 123456
})

1
挽救了这一天 :D - Omer Shacham

-1

S3

Paperclip S3 integration实际上相对简单 - 你最好参考this Railscast关于如何使用Paperclip的内容,以及前面链接的文档来了解Paperclip的工作原理;然后你就可以将其连接到S3。

--

简而言之,Paperclip基本上会获取文件对象并将相关数据保存到您的数据库中。文件的存储取决于您与Paperclip关联的服务。
我的意思是说,这个gem的两个元素(数据分配和文件存储)是不同的元素,如果您可以让Paperclip处理传入的文件,那么您已经完成了一半的工作:

纸夹

默认实现:

#app/models/page.rb
Class Page < ActiveRecord::Base
   has_attached_file :photo
end

这将允许您将“附件”保存到您的Page数据库中:

#app/controllers/pages_controller.rb
Class PagesController < ApplicationController
   def new
       @page = Page.new
   end

   def create
       @page = Page.new(page_params)
   end

   private

   def page_params
      params.require(:page).permit(:title, :other, :information, :photo)
   end
end

#app/views/pages/new.html.erb
<%= form_for @page do |f| %>
   <%= f.file_field :photo %>
   <%= f.submit %>
<% end %>

这将直接处理Paperclip上传到您自己的应用程序(将文件存储在public/system目录中)

为了使其与S3配合工作,您只需将S3凭据添加到模型中(从Paperclip文档中获取):

#app/models/page.rb
Class Page < ActiveRecord::Base
   has_attached_file :photo,
      :storage => :s3,
      :s3_credentials => Proc.new{|a| a.instance.s3_credentials }

   def s3_credentials
      {:bucket => "xxx", :access_key_id => "xxx", :secret_access_key => "xxx"}
   end
end

路径

如果您想调用文件的"S3"文件路径 - 您需要执行以下操作:

#app/controllers/pages_controller.rb
Class PagesController < ApplicationController
   def show
      @page = Page.find 3
      @page.photo.url #-> yields S3 path ;)
   end
end

1
Rich Peck,我的问题是文件已经在S3中了。我不想在S3中创建一个新文件,而是告诉Paperclip使用那个文件。 - Hommer Smith
好的,让我为您修改答案! - Richard Peck
我已经尝试设置paperclip所期望的属性(file_size、updated-at、file_name、content_type),但是没有成功。实际上,当我尝试访问paperclip属性时,我得到了以下错误:ArgumentError: missing required :bucket option。 - Hommer Smith

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接