Rails:如何使用Paperclip防止重复上传照片?

10

如果用户尝试使用Paperclip上传相同的照片到Rails应用程序中,有没有办法引发验证错误? Paperclip似乎没有提供此功能...

我正在使用Rails 2.3.5和Paperclip(显然)。


解决方案:(至少之一)

采用Beerlington的建议,我决定使用MD5校验和比较:

class Photo < ActiveRecord::Base
  #...
  has_attached_file :image #, ...

  before_validation_on_create :generate_md5_checksum
  validate :unique_photo
  #...

  def generate_md5_checksum
    self.md5_checksum = Digest::MD5.hexdigest(image.to_file.read)
  end

  def unique_photo
    photo_digest = self.md5_checksum
    errors.add_to_base "You have already uploaded that file!" unless User.find(self.user_id).photos.find_by_md5_checksum(photo_digest).nil?
  end

  # ...
end

然后我只需向我的photos表中添加一个名为md5_checksum的列,就完成了!现在,如果您尝试上传相同的照片,我的应用程序会抛出一个验证错误!不知道这种方法的效率如何,所以欢迎重构!谢谢!

如果你在网上寻找图像比较算法,你会发现一些dll文件(由Bolide软件发布),可以判断两个图像是否相同,但在Rails应用程序中并没有太大用处。你可能可以尝试编写自己的算法,但我不知道这是否值得麻烦。 - stephenmurdoch
4个回答

11

对于图像文件,尝试进行MD5哈希处理如何? 如果是完全相同的文件,则两个图像的MD5哈希值将相同。


1
小心!您正在对一个二进制表示进行指纹识别,而通常有数百万个二进制文件在计算机屏幕上会显示完全相同。从愚蠢的:我曾经通过在照片编辑软件中打开和关闭文件来更改图像(元数据更改)。到恶意的:只需更改一些元数据,或在末尾添加一些字节(大多数软件将忽略),或稍微调整大小或重新采样,就可以再次上传图像。 - Simon B.

10

对于其他尝试实现此功能的人,请注意Paperclip现在已经内置了md5哈希。 如果您的模型中有一个名为 [attachment]_fingerprint 的属性,Paperclip将使用MD5填充它。

由于我已经拥有一个名为hash_value的列,因此我创建了一个“虚拟”属性称为fingerprint

#Virtual attribute to have paperclip generate the md5
def picture_fingerprint
  self.hash_value
end

def picture_fingerprint=(md5Hash)
  self.hash_value=md5Hash
end

使用rails3和sexy_validations,我能够简单地在我的模型顶部添加以下内容,以确保在保存模型之前hash_value是唯一的:

validates :hash_value, :uniqueness => { :message => "Image has already been uploaded." }

3
当您的图像具有已修改的EXIF元数据时,可能会遇到问题。我曾经遇到过这种情况,不得不提取像素值,并计算它们的MD5,以忽略由Wordpress等造成的更改。您可以在我们的博客中了解更多信息:http://www.amberbit.com/blog/2013/12/20/similar-images-detection-in-ruby-with-phash/ 但是基本上您需要使用某些工具(如RMagick)从图像中获取像素数据,将其连接为字符串,并计算出MD5。

0

正如Stephen所指出的,你最大的问题是如何确定一个文件是否是重复的,而这并没有明确的答案。

如果这些是用数码相机拍摄的照片,你需要比较EXIF数据。如果EXIF数据匹配,则该照片很可能是重复的。如果它是重复的,那么你可以告知用户。不过,你需要先接受上传,以便检查EXIF数据。

我应该提到,EXIFR是一个很好的Ruby gem,用于检查EXIF数据。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接