Carrierwave - 当添加或删除多张图片时,多图上传速度过慢

4
我正在遵循 CarrierWave Wiki 中的这篇文章https://github.com/carrierwaveuploader/carrierwave/wiki/How-to%3A-Add-more-files-and-remove-single-file-when-using-default-multiple-file-uploads-feature,使用 CarrierWave 多文件上传功能,在我的系统中为模型添加更多图像并删除图像。
该文章中的主要代码如下:
def add_more_images(new_images)
  images = @gallery.images 
  images += new_images
  @gallery.images = images
end

def remove_image_at_index(index)
  remain_images = @gallery.images # copy the array
  deleted_image = remain_images.delete_at(index) # delete the target image
  deleted_image.try(:remove!) # delete image from S3
  @gallery.images = remain_images # re-assign back
end

它可以工作。然而,速度太慢了。我查看了日志,整体处理时间如下:
  1. 上传1张图片: 例如需要5000ms
  2. 添加1张图片: 例如需要8500ms (2张图片)
  3. 再添加1张图片: 例如需要12000ms (3张图片)
  4. 删除1张图片: 例如需要8400ms (回到2张图片)
我在本地机器上测试了作者编写的此解决方案的示例应用程序,速度也非常慢。
似乎CarrierWave即使我们只添加或删除1张图片,也会重新上传和重新处理所有图片。我认为这是因为我们将新的图像数组重新分配回@ gallery,所以它将旧图像视为新图像。
还有一个相关问题https://github.com/carrierwaveuploader/carrierwave/issues/1704#issuecomment-259106600 是否有任何更好的解决方案来使用CarrierWave多重上传功能添加和删除图像?

谢谢。

1个回答

0

当你调用model.images = remain_images时,carrierwave会上传所有的图片。因此,你在一列中存储的图片越多,上传所需的时间就越长。 参见:mount.rb#L300, mounter.rb#L40

我之前也遇到过这个问题,以下是我的代码:

new_images = self.logo_images.clone
4.times do |t|
  next if !(image = params[:"logo_image#{t + 1}"])
  new_images[t] = image
  changed = true
end
self.logo_images = new_images if changed
...
self.save if changed

这就是hack的方法...

(在carrierwave 1.0.0carrierwave-aws 1.1.0下运行良好)

mounter = self.send(:_mounter, :logo_images)
4.times do |t|
  next if !(image = params[:"logo_image#{t + 1}"])
  uploader = mounter.blank_uploader
  uploader.cache!(image)
  mounter.uploaders[t] = uploader
  changed = true
end
mounter.uploaders.each{|s| s.send(:original_filename=, s.file.filename) if !s.filename} if changed 
...
self.save if changed

我在跟踪你的代码时遇到了麻烦。看起来对于每个提供的 logo_image[x] 参数,它都会将图像缓存并添加到一个新的 blank_uploader 中,然后迭代所有新的上传器并分配 original_filename。所以假设我们之前有4张图片,现在用户只发送了3个参数(表示删除的图像)...那么这如何防止重新上传原始的3张图片呢? - Codosapien
代码只能添加或替换图像。让 logo_images[nil, image1, image2],用户上传一个新的图像 params[:logo_image3]。如果您使用 add_more_images([params[:logo_image3]]),carrierwave 将上传 image1image2params[:logo_image3]。但如果您使用我的代码,它只会上传 params[:logo_image3] - khiav reoy
我不确定如何删除图片。你可以尝试使用 mounter.uploaders[t]&.remove! 删除图片,使用 mounter.uploaders.delete_at(t) 删除上传器。然后遍历所有的上传器并分配原始文件名。 - khiav reoy

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