1

While uploading 4MB or more than big size image, it should automatically compress less than 1MB. Can anybody tell how to do this in angularjs. The sample file is,

JSFIDDLE

var myApp = angular.module('myApp', []);

myApp.directive('fileModel', ['$parse', function ($parse) {
    return {
        restrict: 'A',
        link: function(scope, element, attrs) {
            var model = $parse(attrs.fileModel);
            var modelSetter = model.assign;
            
            element.bind('change', function(){
                scope.$apply(function(){
                    modelSetter(scope, element[0].files[0]);
                });
            });
        }
    };
}]);

myApp.service('fileUpload', ['$http', function ($http) {
    this.uploadFileToUrl = function(file, uploadUrl){
        var fd = new FormData();
        fd.append('file', file);
        $http.post(uploadUrl, fd, {
            transformRequest: angular.identity,
            headers: {'Content-Type': undefined}
        })
        .success(function(){
        })
        .error(function(){
        });
    }
}]);

myApp.controller('myCtrl', ['$scope', 'fileUpload', function($scope, fileUpload){
    
    $scope.uploadFile = function(){
        var file = $scope.myFile;
        console.log('file is ' );
        console.dir(file);
        var uploadUrl = "/fileUpload";
        fileUpload.uploadFileToUrl(file, uploadUrl);
    };
    
}]);
<div ng-controller = "myCtrl">
    <input type="file" file-model="myFile"/>
    <button ng-click="uploadFile()">upload me</button>
</div>

This is the code for file uploading using angularjs. I want to upload more images. If I upload images the size as 3MB or 2MB do not show any messages like, "The file size is big" or something. It should compress automatically less than 1MB and it should upload that image. Any possibilities are there to do this usning angularjs? Is this possible in angularjs?

sathish kumar
  • 916
  • 1
  • 21
  • 58

2 Answers2

0

Yes, Node is my server

To compress image use the tinypng nodejs package

npm install --save tinify

Do authentication

var tinify = require("tinify");
tinify.key = "YOUR_API_KEY";

Compress the file

var source = tinify.fromFile("unoptimized.jpg");
source.toFile("optimized.jpg");

You can also upload an image from a buffer (a string with binary) and get the compressed image data.

var fs = require("fs");
fs.readFile("unoptimized.jpg", function(err, sourceData) {
  if (err) throw err;
  tinify.fromBuffer(sourceData).toBuffer(function(err, resultData) {
    if (err) throw err;
    // ...
  });
});

You can do lot of other amazing image manipulations. Check the docs here

kiranvj
  • 32,342
  • 7
  • 71
  • 76
0

I recently worked out this problem for myself using the tinify package and found the docs to be somewhat lacking.

I have a Vue front end collecting file uploads from the user using vue2dropzone. These are sent to a node / Express back end. I have a need to compress the file and upload it to an S3 instance without storing on disk. That means using multer memory storage. As a result there won’t be an ability to use tinify.fromFile() as there is no file stored locally.

In my images middleware:

Const multer = require(“multer”);
const tinify = require("tinify");

tinify.key = "your_key";

exports.singleFile = multer({ storage: multer.memoryStorage() }).fields([{ name: "file", maxCount: 1 }]);

exports.uploadCompImage = async (req, res, next) => {
   try {
      const fileName = `${req.params.name}${path.extname(req.files.file[0].originalname)}`;
      const source = tinify.fromBuffer(req.files.file[0].buffer);
      source.store({
         service: "s3",
         aws_access_key_id: "your_id",
         aws_secret_access_key: "your_key
         region: "your_region",
         headers: {
            "Cache-Control": "public"
         },
         path: `your_bucket/your_folder/${fileName}`
      });
      return res.status(200).send(`path_to_file/${fileName}`)
   } catch (err) {
      console.log(err);
      next(err);
   }
}

Then in my routes file:

Const images = require(“../middleware/images”);

// skipped several lines for brevity

productRouter
      .route("/images/:name")
      .post(images.singleFile, images.uploadCompImage)

This process creates a multer singleFile upload to memoryStorage, making the file available at req.files.file[0] (req.files[“file”] because I specified “file” as the name in multer fields, loop through this array if uploading multiple). After setting that up I get the file name, set the source by using tinify to read from req.files.file[0].buffer as a buffer. Then I set the source to my s3 instance and send back a public link to the file.

Hopefully this answer helps you. I could definitely see altering the process to change where the file goes or even write it to disk by altering the multer options.