简体   繁体   English

将现有S3文件链接为回形针附件

[英]Link existing S3 file as paperclip attachment

I have an external service that creates files and stores them into S3 (that my Rails app has access too). 我有一个外部服务,它创建文件并将它们存储到S3(我的Rails应用程序也可以访问)。

I want to be able to use Paperclip in order to store that S3 object, as well as a thumbnail of it. 我希望能够使用Paperclip来存储S3对象及其缩略图。 I haven't been able to find documentation on how to use Paperclip with files that are already on S3. 我无法找到有关如何将Paperclip与已存在于S3上的文件一起使用的文档。 So, my code should look like: 所以,我的代码应如下所示:

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

So, in other words: 所以,换句话说:

How can I tell PaperClip that my attachment is already in S3? 如何告诉PaperClip我的附件已经在S3中了?

EDIT: 编辑:

Here is what I have so far: 这是我到目前为止:

I know the file_name, the content_length and the content_type of the file that is already uploaded in S3. 我知道已在S3上传的文件的file_name,content_length和content_type。 So, since the association is a Page has_attached_file :screenshot 所以,因为关联是一个Page has_attached_file:screenshot

This is what I do: 这就是我做的:

@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)

So, now I can do: 那么,现在我可以这样做:

@page.screenshot and I see the paperclip object. @ page.screenshot我看到了回形针对象。 However, when I do: 但是,当我这样做时:

@page.screenshot.url => The url is not the one that I originally stored the image. @page.screenshot.url =>网址不是我最初存储图片的网址。

I've managed to solve this problem with paperclip interpolations : 我已设法用回形针插值来解决这个问题:

  1. Define in your model a field, witch would store path to the uploaded files 在模型中定义一个字段,巫婆会存储上传文件的路径
  2. Load the paperclip attachment info to DB through property update 通过属性更新将回形针附件信息加载到DB
  3. With interpolations specify a paperclip attachment :path, so it first looks for uploaded file, and then for default 使用插值指定回形针附件:path,因此它首先查找上载的文件,然后是默认值
  4. Profit! 利润!

This will do the trick, because of how S3 storage composes urls : 这将解决问题,因为S3存储如何组成URL

path: This is the key under the bucket in which the file will be stored. path:这是存储文件的存储区下的密钥。 The URL will be constructed from the bucket and the path. URL将从存储桶和路径构造。 This is what you will want to interpolate. 这是您想要插入的内容。 Keys should be unique, like filenames, and despite the fact that S3 (strictly speaking) does not support directories, you can still use a / to separate parts of your file name. 密钥应该是唯一的,比如文件名,尽管S3(严格来说)不支持目录,但您仍然可以使用/来分隔文件名的各个部分。

Here are more details with code: 以下是代码的更多细节:

Model 模型

class MyModel
    has_attached_file :file, path: ":existent_file_or_default", storage: :s3
end

Paperclip interpolations 回形针插值

Put this under config/initializers 把它放在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

Attach existent items 附加现有项目

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
})

S3 S3

Paperclip S3 integration is actually relatively simple - you'll be best looking at this Railscast on how to use Paperclip, and the afore-linked documentation to give you an idea on how Paperclip works; Paperclip S3集成实际上相对简单 - 您最好看看这个Railscast如何使用Paperclip,以及上面链接的文档,让您了解Paperclip的工作原理; then you can just connect it to S3 然后你可以将它连接到S3

-- -

In short, Paperclip basically takes a file object & saves the relevant data to your db. 简而言之,Paperclip基本上采用文件对象并将相关数据保存到数据库中。 The storage of the file is dependent on the service you associate with Paperclip 文件的存储取决于您与Paperclip关联的服务

What I'm trying to say is the two elements (data allocation & file storage) are two different elements of the gem, and if you can get Paperclip to handle the inbound files, you're half-way there: 我想说的是两个元素(数据分配和文件存储)是gem的两个不同元素,如果你可以让Paperclip来处理入站文件,你就在那里:


Paperclip 回形针

Default implementation: 默认实施:

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

This will allow you to save an "attachment" to your Page database: 这将允许您将“附件”保存到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 %>

This will handle Paperclip uploads directly to your own app (storing the files in the public/system directory) 这将直接处理Paperclip上传到您自己的应用程序(将文件存储在public/system目录中)

In order to get it to work with S3, you just have to add the S3 credentials to the model (taken from the Paperclip documentation ): 为了使其与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

Path 路径

If you'd like to call the "S3" filepath for your file - you'll have to do this: 如果您想为文件调用“S3”文件路径 - 您必须这样做:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM