2013-04-08 77 views
6

我想确定一个远程URL是否是一个图像。大多数网址都有.jpg,.png等等,但是一些图片,比如谷歌图片,没有扩展名。载波图像扩展

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

我使用FastImage确定URL是否是一个图像尝试。它的工作原理是当任何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 
+0

也许可以使用正则表达式来允许任何http://encrpyted-tbn0.gstatic上传 – ahmet 2013-04-08 17:16:03

回答

3

如果你所有的一起工作就是这样,你可以发送HEAD请求到服务器,以获得理想的图像内容类型的URL。从可以得到扩展

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

我相信,因为它确保了文件扩展名的存在时,内容类型设置正确,这将解决您有还有问题。

UPDATE:

carrierwave的主支路具有不同的解决方案,以使用该Content-Disposition头找出文件名这个问题。以下是github上的相关请求。

+0

这太棒了!为什么你没有向Carrierwave做出pull请求,这显然是现代图像服务器和所有东西的更好方法... – 2013-10-16 09:43:30

+0

我实际上正在提交一个@NielsKristian :-D – Hamed 2013-10-16 21:00:21

+0

我认为它会欢迎https://github.com/carrierwaveuploader/carrierwave/issues/1247 :-) – 2013-10-17 08:51:52