0

How can I drag and drop multiple image on HTML page, resize the images at client side and download the resized images to computer? I want to accomplish this without any server side processing.

I have tried below solution where one image can be uploaded (using drag and drop) and resized and shown on page, how can I extend this for multiple images?

// Required for drag and drop file access
 jQuery.event.props.push('dataTransfer');
 $(function(){
  var dropTimer;
  var dropTarget = $('.dragArea');
  var fileInput = $('#imageFile');
  dropTarget.on("dragover", function(event) {
   clearTimeout(dropTimer);
   if (event.currentTarget == dropTarget[0]) {
    dropTarget.addClass('over');
   }
   return false; // Required for drop to work
  });
  dropTarget.on('dragleave', function(event) {
   if (event.currentTarget == dropTarget[0]) {
    dropTimer = setTimeout(function() {
     dropTarget.removeClass('over');
    }, 200);
   }
  });
  handleDrop = function(files){
   dropTarget.removeClass('over');
   var file = files[0]; // Multiple files can be dropped. Lets only deal with the "first" one.
   if (file.type.match('image.*')) {
    resizeImage(file, 1000, function(result) {
     $('#resultImage').attr('src', result);
     $('.resultImageWrapper').show();
    });
   } else {
    alert("That file wasn't an image.");
   }
  };
  dropTarget.on('drop', function(event) {
   event.preventDefault(); // Or else the browser will open the file
   handleDrop(event.dataTransfer.files);
  });
  fileInput.on('change', function(event) {
   handleDrop(event.target.files);
  });
  resizeImage = function(file, size, callback) {
   var fileTracker = new FileReader;
   fileTracker.onload = function() {
    var image = new Image();
    image.onload = function(){
     var canvas = document.createElement("canvas");
     /*
     if(image.height > size) {
      image.width *= size / image.height;
      image.height = size;
     }
     */
     if(image.width > size) {
      image.height *= size / image.width;
      image.width = size;
     }
     var ctx = canvas.getContext("2d");
     ctx.clearRect(0, 0, canvas.width, canvas.height);
     canvas.width = image.width;
     canvas.height = image.height;
     ctx.drawImage(image, 0, 0, image.width, image.height);
     callback(canvas.toDataURL("image/png"));
    };
    image.src = this.result;
   }
   fileTracker.readAsDataURL(file);
   fileTracker.onabort = function() {
    alert("The upload was aborted.");
   }
   fileTracker.onerror = function() {
    alert("An error occured while reading the file.");
   }
  };
 });
body {
   padding: 50px;
   font: 16px Helvetica;
  }
  .dragArea {
   background-color: #efefef;
   border: 3px dashed #cccccc;
   border-radius: 10px;
   text-align: center;
   padding: 50px;
  }
  .dragArea.over {
   border-color: #ff0000;
   background-color: #FFE9EA;
  }
  .resultImageWrapper {
   display: none;
   margin-top: 50px;
   text-align: center;
  }
  #resultImage {
   box-shadow: rgba(0,0,0,0.4) 0 2px 5px;
  }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

<!DOCTYPE html>
<html>
<head>
 <title>Angular HTML5 Preview, Crop And Upload</title> 
</head>
<body>

<div class="dragArea">
 <h3>Drag & Drop File Here</h3>
 <h4>Or Select File:</h4>
 <div>
  <input type="file" id="imageFile"/>
 </div>
</div>

<div class="resultImageWrapper">
 <img src="" alt="" id="resultImage" width="500" />
</div>

</body>
</html>
Rohan
  • 11
  • 5
  • If you read the comments in your code you'll find `// Multiple files can be dropped. Lets only deal with the "first" one.` This comment is made after `var file = files[0]`. So just iterate through `files` instead of using on the first one. Ps: in `resizeImage`, you don't need the FileReader, simply use image.onload = URL.createObjectURL(file)`. – Kaiido Feb 03 '18 at 09:26
  • @kalido I tried doing that but then it renders all the images in same resolution I uploaded and resizing does not work. – Rohan Feb 03 '18 at 09:27
  • https://xianshenglu.github.io/html5/html5%20%E9%9B%AA%E7%A2%A7%E5%9B%BE%E7%94%9F%E6%88%90%E5%99%A8/index.html – xianshenglu Feb 03 '18 at 09:36
  • or http://alloyteam.github.io/gopng/### – xianshenglu Feb 03 '18 at 09:37

1 Answers1

0

As one of the comment states, you are currently only dealing with one file. You will have to iterate through all the files if you want to handle multiple images:

// Required for drag and drop file access
jQuery.event.props.push('dataTransfer');
$(function() {
  var dropTimer;
  var dropTarget = $('.dragArea');
  var fileInput = $('#imageFile');
  dropTarget.on("dragover", function(event) {
    dropTarget.addClass('over');
    return false; // Required for drop to work
  });
  dropTarget.on('dragleave', function(event) {
    dropTarget.removeClass('over');
  });
  handleDrop = function(files) {
    dropTarget.removeClass('over');
    var file;
    // iterate through all dropped files
    for (var i = 0; i < files.length; i++) {
      file = files[i];
      if (file.type.match('image.*')) {
        resizeImage(file, 100, function(result) {
          // we now need to append a new Image instead of reusing a single one
          $('.resultImageWrapper').append(
            $('<img>', {src: result})
          )
          $('.resultImageWrapper').show();
        });
      } else {
        alert("That file wasn't an image.");
      }
    }
  };
  dropTarget.on('drop', function(event) {
    event.preventDefault(); // Or else the browser will open the file
    handleDrop(event.dataTransfer.files);
  });
  fileInput.on('change', function(event) {
    handleDrop(event.target.files);
  });
  resizeImage = function(file, size, callback) {
    // no need for a FileReader, a blobURI is better
    var image = new Image();
    image.onload = function() {
      var canvas = document.createElement("canvas");
      /*
      if(image.height > size) {
       image.width *= size / image.height;
       image.height = size;
      }
      */
      if (image.width > size) {
        image.height *= size / image.width;
        image.width = size;
      }
      var ctx = canvas.getContext("2d");
      canvas.width = image.width;
      canvas.height = image.height;
      ctx.drawImage(image, 0, 0, image.width, image.height);
      callback(canvas.toDataURL("image/png"));
    };
    image.src = URL.createObjectURL(file);

  };
});
body {
  padding: 50px;
  font: 16px Helvetica;
}

.dragArea {
  background-color: #efefef;
  border: 3px dashed #cccccc;
  border-radius: 10px;
  text-align: center;
  padding: 50px;
}

.dragArea.over {
  border-color: #ff0000;
  background-color: #FFE9EA;
}

.resultImageWrapper {
  display: none;
  margin-top: 50px;
  text-align: center;
}

.resultImageWrapper>img {
  box-shadow: rgba(0, 0, 0, 0.4) 0 2px 5px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

<div class="dragArea">
  <h3>Drag & Drop File Here</h3>
  <h4>Or Select File:</h4>
  <div>
    <input type="file" id="imageFile" />
  </div>
</div>

<div class="resultImageWrapper">

</div>
Kaiido
  • 123,334
  • 13
  • 219
  • 285
  • This worked, Thanks !!! Is there a way to change default name 'download' of this resized images. i.e When I right click and try to save the resized files Or try to drag and drop them on desktop, I noticed the name of all of this images come by default as download.png – Rohan Feb 03 '18 at 20:04