2017-02-21 5 views
0

Я работаю над приложением, которое позволяет пользователям публиковать события. Я использую NodeJS, Express и Mongo.Как предотвратить загрузку загруженного изображения при редактировании формы?

Я создал форму, которая позволяет пользователям вводить сведения о мероприятии и загружать изображение, относящееся к событию. Я также создал форму, которая позволяет пользователю редактировать информацию о событии.

форма выглядит следующим образом:

enter image description here

Проблема:

  1. Пользователь заполняет форму с подробной информацией о событиях и прикрепляет изображение.
  2. Пользователь представляет образует
  3. Пользователь решает, что он хочет изменить название события, но Nothing Else
  4. Пользователь щелкает редактирования события, меняет название и представляет
  5. Проблемы: Даже если пользователь Ждет» t удалить изображение, связанное с событием, изображения больше нет.

Вот часть моего 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, предварительный просмотр (скрытый изначально) и dropbox. Когда изображение загружается, класс «скрытый» удаляется из предварительного просмотра и добавляется в dropbox.

Вот часть файла 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> 

Сценарий выше успешно делает изображение в страницу редактирования, следующим образом.

enter image description here

Но при нажатии кнопки отправить, изображение не отображается.

Это файл маршрута 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 = undefined. И изображение больше не связано с событием.

здравый смысл сказал бы это сделать

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

Но если вы сделаете это, вы ввести новую проблему: если пользователь редактирует событие и удаляет изображение (то есть решает, что он не хочет, чтобы изображение, связанное с событием), изображение никогда не удаляется.

Любая идея, как решить эту проблему? Я знаю, что мне нужно что-то сделать в скрипте edit.ejs ... В частности, мне нужно создать файл изображения ... Но я не уверен, как подойти к этому

ответ

0

Так что я получил это для работы через хак, я ДЕЙСТВИТЕЛЬНО не люблю. Я уверен, что есть лучший, более чистый, стандартный способ работы с 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); 
    }); 
}); 

Хорошо, так что его грязно.

Любое лучшее решение было бы оценено