Rails Rails4 + Carrierwave 下實現 JSON 形式的文件上傳 API

cn_boris · 2015年08月15日 · 最后由 jackxu 回复于 2015年08月17日 · 3368 次阅读

相較於傳統的 multipart/form-data 表單上傳,在 API 中將文件以 Base64 形式編碼後置於 JSON 中會是更為妥貼的實現方式。

Carrierwave 是一個知名的文件上傳 GEM。下文將主要闡述在 Rails4 與 Carrierwave 中如何實現一個不依賴於具體數據庫的獨立上傳 API。

# app/models/media.rb

class Media  
  include ActiveModel::Model

  attr_accessor :path, :type, :original_filename, :content_type
  attr_writer :file
  validates :path, presence: true
  validates :original_filename, presence: true
  validates :content_type, presence: true
  validates :type, inclusion: %w(logo image video)

  def file
    data = StringIO.new(Base64.decode64(@file))
    data.class.class_eval { attr_accessor :original_filename, :content_type } # 確保與 Carrierwave 所預期的格式保持一致
    data.original_filename = original_filename
    data.content_type = content_type
    data # 返回 data
  end

  def upload!
    uploader = Object.const_get("#{type.classify}Uploader").new # 允許按需上傳到不同的 Uploader
    uploader.store! file
    self.path = uploader.url
  end

end  

為保證更好的閱讀體驗,全文請見我的博客: https://hacker.design/design-json-upload-api-base-by-carrierwave/

文件全部读入内存,内存很容易耗光吧。

其实参考一下 twitter tumblr 的接口就能发现一个更好的上传文件的方法. 单独一个接口,只做文件上传服务,接受 form-data,然后返回 json. 用 base64 上传文件,无论客户端还是服务端,压力都很大。

https://dev.twitter.com/rest/public/uploading-media twitter api

#2 楼 @ch3n 赞成,我们也经历过这个变化过程。

#2 楼 @ch3n 关注一下!哈哈

#1 楼 @rei 文件读入会被读入内存,但据我的了解这样使用 StringIO 并不会引发内存泄露,只是 request 过多会导致读入内存过多,然而 GC 还来不及回收是吧

需要 登录 后方可回复, 如果你还没有账号请 注册新账号