【问题标题】:Carrierwave image extensions载波图像扩展
【发布时间】:2013-03-30 20:29:03
【问题描述】:

我正在尝试确定远程 url 是否是图像。大多数网址都有 .jpg、.png 等...但有些图片(例如 google 图片)没有扩展名...即

https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSbK2NSUILnFozlX-oCWQ0r2PS2gHPPF7c8XaxGuJFGe83KGJkhFtlLXU_u

我尝试使用 FastImage 来确定网址是否为图像。它可以在任何 URL 输入时工作...

如何确保远程 url 使用 FastImage 并且上传的文件使用白名单?这是我的上传器中的内容。 Avatar_remote_url 无法识别...我应该在上传器中做什么来仅测试远程 url 而不是常规文件。

  def extension_white_list
    if defined? avatar_remote_url && !FastImage.type(CGI::unescape(avatar_remote_url)).nil?
      # ok to process
    else # regular uploaded file should detect the following extensions
      %w(jpg jpeg gif png)
    end
  end

【问题讨论】:

标签: ruby-on-rails ruby-on-rails-3 image upload carrierwave


【解决方案1】:

我遇到了一个类似的问题,即从原始版本创建不同版本失败,因为 ImageMagick 由于缺少扩展名而无法确定要使用的正确编码器。这是我在 Rails 中应用的一个猴子补丁,它解决了我的问题:

module CarrierWave
  module Uploader
    module Download
      class RemoteFile
        def original_filename
          value = File.basename(file.base_uri.path)
          mime_type = Mime::Type.lookup(file.content_type)
          unless File.extname(value).present? || mime_type.blank?
            value = "#{value}.#{mime_type.symbol}"
          end
          value
        end
      end
    end
  end
end

我相信这也将解决您遇到的问题,因为它确保在适当设置内容类型时存在文件扩展名。

更新:

carrierwave 的 master 分支对此问题有不同的解决方案,它使用 Content-Disposition 标头来找出文件名。这是github 上的相关拉取请求。

【讨论】:

  • 这太棒了!你为什么不向 Carrierwave 发出拉取请求,这显然是现代图像服务器和所有东西的更好方法......
  • 我实际上正在提交一个@NielsKristian :-D
  • 我已经创建了拉取请求here
  • 只是想让你知道我已经合并了@Hamed 的 PR。谢谢!
【解决方案2】:

我正在使用您提供的代码以及CarrierWave Wiki for validating remote URLs 中提供的一些代码。

您可以在lib/remote_image_validator.rb 中创建一个新的验证器。

require 'fastimage'

class RemoteImageValidator < ActiveModel::EachValidator
  def validate_each(object, attribute, value)
    raise(ArgumentError, "A regular expression must be supplied as the :format option of the options hash") unless options[:format].nil? || options[:format].is_a?(Regexp)
    configuration = { :message => "is invalid or not responding", :format => URI::regexp(%w(http https)) }
    configuration.update(options)

    if value =~ configuration[:format]
      begin
        if FastImage.type(CGI::unescape(avatar_remote_url))
          true
        else
          object.errors.add(attribute, configuration[:message]) and false
        end
      rescue
        object.errors.add(attribute, configuration[:message]) and false
      end
    else
      object.errors.add(attribute, configuration[:message]) and false
    end
  end
end

然后在你的模型中

class User < ActiveRecord::Base
  validates :avatar_remote_url,
    :remote_image => { 
      :format => /(^$)|(^(http|https):\/\/[a-z0-9]+([\-\.]{1}[a-z0-9]+)*\.[a-z]{2,5}(([0-9]{1,5})?\/.*)?$)/ix,
      :unless => remote_avatar_url.blank?
    }
end

【讨论】:

    【解决方案3】:

    如果您只需要使用这样的 url,您可以向服务器发送 HEAD 请求以获取图像的内容类型。从中您可以获取扩展名

    require 'net/http'
    require 'mime/types'
    
    def get_extension(url)
      uri = URI.parse(url)
      http = Net::HTTP.new(uri.host, uri.port)
      http.use_ssl = true if uri.scheme == 'https'
      request = Net::HTTP::Head.new(uri.request_uri)
      response = http.request(request)
      content_type = response['Content-Type']
      MIME::Types[content_type].first.extensions.first
    end
    

    【讨论】:

      猜你喜欢
      • 2016-11-06
      • 2019-06-10
      • 2019-02-26
      • 2016-06-30
      • 2012-11-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-06-06
      相关资源
      最近更新 更多