node.jsfile-uploaddropzone.jsajax-upload

Node js Dropzone js - Upload file without submitting form


I am new in node js and trying to integrate single file upload using dropzone js. I want to upload image before submitting form. I have managed to call the upload action before submitting.

Here is my html code:

<form id="add_user" name="add_user" class="form-horizontal" action="/add-new-user" method="POST">
    <div class="directory-bg text-center">
        <div class="directory-overlay">
                <span id="imageuploader">
                    <input name="profileimg" id="profileimg" type="hidden" value="">
                    <img id="ws_user_avatar" class="rounded-circle thumb-lg img-thumbnail dropzone" data-thumb="public/assets/images/users/user.png" src="public/assets/images/users/user.png" alt="Generic placeholder image">
                    <!--<div class="fallback">
                        <input name="image" id="image" type="file">
                    </div>-->
                    <a href="javascript:void(0)" id="remove_img">x</a>
                </span>
        </div>
    </div>

    <div class="directory-content p-4">
        <div class="mt-4">
            <% if(success != "") {%> 
                <div class="alert alert-success" role="alert">
                    <strong>Done!</strong> <%= success %>
                </div>
            <% } %>
            <div class="row">                                                            
                <div class="col-md-12">
                    <div class="mb-3">
                        <label class="form-label" for="email">Email Address</label>
                        <input type="email" class="form-control" name="email" id="email" placeholder="Email Address" data-key="Email Address" autocomplete="off" autofill="false">
                    </div>
                </div>
            </div>

            <div class="row">
                <div class="col-md-6">
                    <div class="mb-3">
                        <label class="form-label" for="fname">First Name</label>
                        <input type="text" class="form-control" name="fname" id="fname" placeholder="First Name" data-key="First Name" autocomplete="off" autofill="false">
                    </div>
                </div>
                <div class="col-md-6">
                    <div class="mb-3">
                        <label class="form-label" for="lname">Last Name</label>
                        <input type="text" class="form-control" id="lname" name="lname" placeholder="Last Name" data-key="Last Name" autocomplete="off" autofill="false">
                    </div>
                </div>
            </div>
        </div>
    </div>
</form>

Here is the js code to handle dropzone event

   Dropzone.autoDiscover = false;
        var myDropzone = new Dropzone(".dropzone", {
        url: '/upload-image',
        autoProcessQueue: false,
        uploadMultiple: false,
        maxFiles:2,
        maxFilesize: 2,
        createImageThumbnails:false,
        hiddenInputContainer: "img.rounded-circle",
        init: function(file) {
            var prevFile = null;
            this.on("addedfile", function(file) {
                var $this = this;
                setTimeout(function () {
                    if(file.status == "error"){
                        alert(file.previewTemplate.innerText);
                    } else {
                        if(prevFile){
                            $this.removeFile($this.files[0])
                        }
                        prevFile = file;
                        
                        $("#user_avatar").attr('data-imgname', file.name);
                        previewImage($this);
                    }
                }, 10);
            });
        }
    });

    function previewImage(input){
        let fileReference = input.files && input.files[0];
        if(fileReference){
            var reader = new FileReader();
            reader.onload = (event) => {
                document.getElementById('user_avatar').src = event.target.result;
            }
            reader.readAsDataURL(fileReference); 
        }
    }
    $(document).on('click','#btn_submit', function(e){
        e.preventDefault();
        if(myDropzone.getQueuedFiles().length > 0){
            myDropzone.processQueue();
        } else {
            $("#add_user").submit();
        }
    });

Here is the post handler code in router.js file:

 const express = require('express');
const router = express.Router();

router.post('/upload-image', function(req, res){
    console.log('requested inage',req.files.file.path);
    // fs.readFile(request.files.file.path, function(err, data) {

    //     var newPath = __dirname + "/public/img/xspectra/customlogo.png";
    //     fs.writeFile(newPath, data, function (err) {
    //       console.log("Finished writing file..." + err);
    //       response.redirect("back");
    //     });
    
    //   });
});

When the dropzone myDropzone.processQueue() function called, I get an error message in the post handler function TypeError: Cannot read property 'file' of undefined.

Can anyone suggest me where I am doing wrong?

Many Thanks!


Solution

  • That means that the file uploaded didn't properly make it to your web server. Are you using express-fileupload on the nodejs side to handle the uploads?

    If so, I recommend checking out this link on a really great tutorial