繁体   English   中英

编辑表单时如何防止上传的图像被删除?

[英]How to prevent uploaded image from getting deleted when editing a form?

我正在开发一个允许用户发布事件的应用程序。 我正在使用NodeJS,Express和Mongo。

我创建了一个表单,允许用户输入事件详细信息,并上传与事件有关的图像。 我还创建了一个表单,允许用户编辑事件详细信息。

该表格如下所示:

在此处输入图片说明

问题:

  1. 用户用事件详细信息填写表格并附上图片。
  2. 用户提交表格
  3. 用户决定他要更改事件标题,但没有其他
  4. 用户单击编辑事件,更改标题,然后提交
  5. 问题: 即使用户没有删除与事件关联的图片,该图片也不再存在。

这是我的new.ejs文件的一部分 (用于发布新事件,只需在此处添加以供参考)

<script type="text/javascript" src="/js/eventform.js"></script>
<form action="/events" 
      method="POST" 
      enctype="multipart/form-data" 
      onSubmit="return(validate(this));" // validating user input
      novalidate >

    ....
    ....
    <input name="image" type="file" id="image" accept="image/*" style="display:none" onchange="handleFiles(this.files)">
    <div id="imageBorder" >
        <div id="imageContainer">
            <div id="dropbox">
                 <i class="fa fa-picture-o" aria-hidden="true"></i>
                 <p> Drop image here or click to upload</p>
             </div>
             <div id="preview" class="hidden">
             </div>
             <button id="fileSelect" class="...">Upload Image</button>
             <button id="fileRemove" class="...">Remove Image</button>
        </div>
     </div>
     ....
     ....
</form>

请注意,我正在使用隐藏的输入字段。 我也有两个div,预览(最初隐藏)和保管箱。 上载图像时,“隐藏”类将从预览中删除,并添加到保管箱。

这是js文件newevent.js的一部分

$(document).ready(function() {
    ....
    eventImageSetup();
    ....
}
....
function eventImageSetup() {
    var dropbox = document.getElementById("dropbox"),
        fileElem = document.getElementById("image"),
        fileSelect = document.getElementById("fileSelect"),
        fileRemove = document.getElementById("fileRemove");
    $(dropbox).height($('#imageBorder').height());
    fileSelect.addEventListener("click", function(e) {
        if (fileElem) {
          fileElem.click();
          e.preventDefault(); // to prevent submit
        }
    }, false);
    fileRemove.addEventListener("click", function(e) {
        e.preventDefault(); // prevent submit
        if(!$('#preview').hasClass('hidden')) { // if there is an image 
            $('#preview').empty(); 
            $('#dropbox').removeClass('hidden');
            $('#preview').addClass('hidden');
            $('#fileSelect').text('Upload Image');
            $('#image').wrap('<form>').closest('form').get(0).reset();
             $('#image').unwrap();
        }    
        removeError($('#imageError'), $('#image'));
    });
    dropbox.addEventListener("dragenter", dragenter, false);
    dropbox.addEventListener("dragover", dragover, false);
    dropbox.addEventListener("drop", drop, false);
}

function handleFiles(files) { 
   var file = files[0];
   .... // some error checking

   var img = document.createElement("img");
   img.id = "uploadedImage";
   img.file = file;
   img.onload = function() {
          adjustImageSize(img);
   };
   $('#dropbox').addClass('hidden');
   $('#preview').removeClass('hidden');
   $('#preview').empty();
   $('#preview').append(img);
   $('#fileSelect').text('Replace Image');

   var reader = new FileReader();
          reader.onload = (function(aImg) {
                 return function(e) {
                 aImg.src = e.target.result;
          };
    })(img);
    reader.readAsDataURL(file);
}    

这是我的edit.ejs文件的一部分

<form action="/events/<%=event._id%>?_method=PUT" 
      method="POST"
      enctype="multipart/form-data" 
      onSubmit="return(validate(this));"
      novalidate >

    <input name="image" type="file" id="image" accept="image/*" style="display:none" onchange="handleFiles(this.files)">

    <div id="imageBorder" >
        <div id="imageContainer">
              <div id="dropbox" class="hidden">
                    <i class="fa fa-picture-o" aria-hidden="true"></i>
                    <p> Drop image here or click to upload</p>
               </div>
               <div id="preview">
                    <script>
                        var imageExists = '<%=event.image%>';
                        if(imageExists) {
                            var myImg = document.createElement("IMG");
                            var source = "../../<%= event.image %>";
                            myImg.src = source; 
                            adjustImageSize(myImg);
                            $('#preview').append(myImg);
                        }
                        </script>
               </div>
               <button id="fileSelect" class="...">Upload Image</button>
               <button id="fileRemove" class="...">Remove Image</button>
            </div>
     </div> <!-- END OF imageBorder -->
     ....
 </form>

上面的脚本成功使图像出现在编辑页面中,如下所示。

在此处输入图片说明

但是,当您单击提交时,该图片不会显示。

这是nodejs路由文件。 你可以在这里看到问题

// UPDATE SPECIFIC EVENT IN DATABASE 
router.put("/:id", upload.single('image'), middleware.checkEventOwnership, function(req, res) {

    var filepath = undefined;
    if(req.file) {
        filepath = req.file.path.substr(7); // Substr to remove "/public"
    }

    req.body.image = filepath;

    Event.findByIdAndUpdate(req.params.id, req.body, function(err, foundEvent) {
       if(err) {
           console.log(err);
           req.flash("error", err);
       } else {
           req.flash("success", "Successfully edited your event");
       }
       res.redirect("/events/" + req.params.id);
    });
});

基本上,如果我不修改编辑表单中的图像,则req.file不存在 因此,req.body.image =未定义。 并且图像不再与事件相关联。

常识会说这样做

    if(req.file) {
        filepath = req.file.path.substr(7); 
        req.body.image = filepath;
    }

但是,如果这样做,则会带来一个新问题:如果用户编辑事件并删除图像(即,确定他不希望该图像与事件关联),则该图像永远不会被删除。

任何想法如何解决这个问题? 我知道我必须在edit.ejs脚本中做一些事情...更具体地说,我需要创建一个图像文件...但是我不确定如何处理这个问题

所以我通过一个我真的不喜欢的hack来解决这个问题。 我敢肯定,有一种更好,更干净,更标准的方式来处理edit.ejs和图像。 换句话说,请帮助我找到更好的解决方案!

这是edit.ejs中的更改

<form action="/events/<%=event._id%>?_method=PUT" 
      method="POST"
      enctype="multipart/form-data" 
      onSubmit="return validate(this) & editPageImageProcessing(this);"
      novalidate >
     ....
     ....
       <div id="preview">
          <script>
                  var imageExists = '<%=event.image%>';
                  if(imageExists) {
                         var myImg = document.createElement("IMG");
                         var source = "../../<%= event.image %>";
                         myImg.src = source; 
                         myImg.name = "previewImage";
                         myImg.id = "previewImage";
                         adjustImageSize(myImg);
                         $('#preview').append(myImg);
                   }
          </script>
      </div>

基本上,我添加了行

                         myImg.name = "previewImage";
                         myImg.id = "previewImage";

并添加了一个功能editPageImageProcessing。

该功能的作用是:如果用户没有上传新图像,也没有删除图像,则创建一个隐藏的输入字段“ hiddenImage”,并将其值作为原始图像的来源。 见下文:

// This function deals with edit image
function editPageImageProcessing(form) {
    // If the user didn't change the image
             // preview would be NOT hidden
             // there would not be a req.file (document.getElementById('image').val == '')
             // we want a hiddenimage input field
    var aFile = document.getElementById('image').value;
    console.log("File: ", aFile);
    var preview = document.getElementById('preview');
    console.log("Preview has hidden class: " + $(preview).hasClass('hidden'));
    if(aFile == '' && !$(preview).hasClass('hidden')) {
        var input = document.createElement('input');
        $(input).attr("name", "hiddenImage");
        $(input).attr("id", "hiddenImage");
        $(input).attr("type", "hidden");
        var myImage = document.getElementById('previewImage');
        $(input).attr("value", myImage.src);
        $('form').append(input); 
    }
    return true;
}

现在,在编辑路线中,我这样做了

// UPDATE SPECIFIC EVENT IN DATABASE 
router.put("/:id", upload.single('image'), middleware.checkEventOwnership, function(req, res) {
    var filepath = undefined;
    if(req.file) { // If user uploaded a new image
        filepath = req.file.path.substr(7); // Substr to remove "/public"
        console.log(filepath);
    } else if(req.body.hiddenImage) { // If user kept the same image
        var index = req.body.hiddenImage.lastIndexOf("/uploads");
        filepath = req.body.hiddenImage.substr(index);
        // req.body.hiddenImage WILL ONLY EXIST if user left image unchanged
    }

    req.body.image = filepath; // If user deleted image, this will be undefined, which is what we want

    Event.findByIdAndUpdate(req.params.id, req.body, function(err, foundEvent) {
       if(err) {
           console.log(err);
           req.flash("error", err);
       } else {
           req.flash("success", "Successfully edited your event");
       }
       res.redirect("/events/" + req.params.id);
    });
});

好的,很乱。

任何更好的解决方案将不胜感激

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM