带Rails的Dropzonejs - 从服务器删除文件

时间:2014-07-06 02:16:55

标签: javascript jquery ruby-on-rails ajax dropzone.js

我正在使用dropzonejs-rails gem并结合dropzone进行文件管理。我上传工作很棒,但删除文件让我感到痛苦。我无法让侦听器附加,以便ajax会命中我的服务器。我的强项是Ruby on Rails,我只有有限的javascript经验,所以这可能是真正的问题......但也许有人可以帮助我解决我[可耻的] 2天的斗争。

Dropzone在上传文件后正在dropzone中正确显示previewTemplate,而addRemoveLinks: true正在缩略图预览中显示删除链接。我的目标是,当用户单击文件的删除链接时,应该向服务器发送请求以删除该文件。我尝试了许多不同的方法来自博客,dropzone常见问题解答,github问题等。我最接近成功的方法是:https://github.com/enyo/dropzone/issues/456

我尝试在成功上传后向.dz-remove按钮添加事件监听器。此侦听器旨在使用ajax请求命中服务器以删除该文件。目前,单击预览缩略图上的删除链接仅从dropzone中删除预览缩略图,但不会使用ajax命中服务器。这是javascript代码:

// Listening for Dropzone upload success
// imageDropzone is the camelized version of the dropzone form's id. 
Dropzone.options.imageDropzone = {
  init: function() {
    this.on("success", function(file, response, event) {

      // Loads image ID to the file preview for use w/deletion
      var elem;
      elem = document.createElement('input');
      elem.setAttribute("name", "id");
      elem.setAttribute("value", response["id"]);
      elem.setAttribute("type", "hidden");
      file.previewTemplate.appendChild(elem);

      // Add the listener to the dz-remove class link
      $('.dz-remove').on("click", (function(e) {
        var imageId, imageToken, _this;
        _this = this;
        e.preventDefault();
        e.stopPropagation();
        imageId = $(_this).parent().find('[name="id"]').val();
        console.log(_this);
        console.log(imageId);
        console.log(imageToken);
        $.ajax({
          url: "/remove_image",
          type: "DELETE",
          dataType: "script",
          data: {
            id: imageId
          }
        });
        return false;
      }), false);
    });
  }
};

因此,它应该找到与单击的删除链接关联的文件信息,并将该信息发送到服务器以获取删除请求。有没有人成功地使用Javascript为Ruby on Rails(Rails 4)应用程序获得这种方法(或更好的方法?)

如果您需要任何其他信息或代码,请与我们联系。谢谢!

1 个答案:

答案 0 :(得分:0)

我最终想出了如何通过"删除文件"使其通过ajax请求进入Rails服务器。通过addRemoveLinks选项随附dropzonejs-rails的按钮(设置为true时)。 (see dropzonejs.com for more info on that)这是在@simmi simmi's answer here的帮助下完成的。

所以,如果有人想知道,这里是coffeescript中的代码。 (抱歉,切换器中间问题。如果你需要JS格式,请使用js2coffee.org转换回JS格式,或者如果我收到请求,我可以发布它。)因为它是在coffeescript中,解释性评论将使用'#'符号

/app/assets/javascripts/upload.js.coffee

  # Note that imageDropzone is the #id of MY dropzone HTML element. Yours may be called myDropzone or otherwise - tailor as needed.
  Dropzone.options.imageDropzone = init: ->
    @on "success", (file, response, event) ->  #triggered by our render JSON's status: 200 "success" response rendered from controller on successful upload.

    # Append the image id as a hidden input
    elem = document.createElement('input')
    elem.setAttribute("name", "image[id]")
    elem.setAttribute("value", response["id"])
    elem.setAttribute("type", "hidden")
    file.previewTemplate.appendChild elem

    # Append the image token as a hidden input.
    # Because images are uploaded as an association (Post model has_many :images), there needs to be a common reference so the Post controller can associate the proper pictures during creation of the Post. 
    elem2 = document.createElement('input')
    elem2.setAttribute("name", "image[token]")
    elem2.setAttribute("value", response["token"])
    elem2.setAttribute("type", "hidden")
    file.previewTemplate.appendChild elem2

    # The "remove file" button's listener needs to be added through "file.previewTemplate" for it to work, but note that "click" does NOT work! 
    # It seemed like the built-in listener gets the "click" call before this one we add here, so it never receives this. 
    # So, I used a "mouseup" listener to have a fighting chance, and it worked. 
    file.previewTemplate.addEventListener "mouseup", (e) ->
      _this = this
      e.preventDefault()
      e.stopPropagation()
      # These next two lines are me grabbing the database reference values I put into the previewTemplate (see above). These are passed through the Ajax call at params. I wanted them to come through hashed like params[:images][:id] & params[:images][:token] for easy use with strong_params.
      imageId = $(_this).parent().find('[name="image[id]"]').val()
      imageToken = $(_this).parent().find('[name="image[token]"]').val()
      $.ajax
        url: "/destroyimage" #This is the route I'm hitting to forward to controller
        type: "DELETE"
        dataType: "script"   #Send as JS
        data:
          image:
            id: imageId
            token: imageToken
      false
    false

以下是控制器信息,以防它有用:

#应用程序/控制器/ images_controller.rb

def create
   @image = current_user.images.build(image_params) # Build through the association

   respond_to do |format|
     if @image.save
       # Send Response: id/token for remove button; status 200 OK for Dropzone success
       format.json { render json: @image, id: @image.id, token: @image.token, :status => 200 }
     else
       # Send Response: status 400 ERROR for Dropzone failure
       format.json { render json: { error: @image.errors.full_messages }, :status => 400 }
     end
   end
 end

 def destroy
   image = current_user.images.where(token: image_params[:token]).where(id: image_params[:id]).take  # Probably a little too redundant on security, but whatever
   respond_to do |format|
     if Image.destroy(image.id)
       format.json { head :ok, :status => 200 }
     else
       format.json { render json: { error: @image.errors.full_messages }, :status => 400 }
     end
   end
 end


 private
 def image_params
   # There's probably a better way to do this, but it worked for me.
   params[:image].present? ? params.require(:image).permit(:id, :filename, :token) : nil
 end

另外,请注意,这是使用Rails CarrierWave gem进行文件上传。我确信它上传宝石的其他文件(纸夹,蜻蜓等)非常相似。