6

I'm trying to determine whether a remote url is an image. Most url's have .jpg, .png etc...but some images, like google images, have no extension...i.e.

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

I've tried using FastImage to determine whether a url is an image. It works when any URL is fed into it...

How could I ensure that remote urls use FastImage and uploaded files use the whitelist? Here is what have in my uploader. Avatar_remote_url isn't recognized...what do I do in the uploader to just test remote urls and not regular files.

  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
4

3 回答 3

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
于 2013-04-11T13:57:25.840 回答
2

我正在使用您提供的代码以及CarrierWave Wiki 中提供的用于验证远程 URL的一些代码。

您可以在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
于 2013-04-17T04:15:15.867 回答
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-Dispositionheader 来找出文件名。这是github上的相关拉取请求。

于 2013-10-15T14:42:56.510 回答