Как автоматически сжать изображение при загрузке файла

При загрузке изображения размером 4 МБ или более оно должно автоматически сжиматься до размера менее 1 МБ. Может ли кто-нибудь сказать, как это сделать в angularjs. Пример файла,

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>

Это код для загрузки файлов с помощью angularjs. Я хочу загрузить больше изображений. Если я загружаю изображения размером 3 МБ или 2 МБ, не отображаются сообщения типа «Размер файла большой» или что-то в этом роде. Он должен автоматически сжимать менее 1 МБ и загружать это изображение. Есть ли какие-либо возможности сделать это с помощью angularjs? Возможно ли это в angularjs?


person sathish kumar    schedule 07.03.2018    source источник
comment
Это должно быть сделано на стороне сервера. Какой у вас сервер, это узел?   -  person kiranvj    schedule 07.03.2018
comment
Да, Node — мой сервер   -  person sathish kumar    schedule 07.03.2018
comment
Возможный дубликат Сжать изображения на стороне клиента перед загрузкой   -  person Jorge Fuentes González    schedule 07.03.2018
comment
@JorgeFuentesGonzález Я думаю, это просто изменение ширины и высоты. Но я хочу сжать изображение менее чем в 1 МБ.   -  person sathish kumar    schedule 07.03.2018
comment
Вы можете изменить ширину/высоту, что уменьшит размер изображения, а также экспортировать его в jpg с желаемым сжатием. Прочитайте пост внимательно, пожалуйста.   -  person Jorge Fuentes González    schedule 07.03.2018


Ответы (2)


Да, Node — мой сервер

Для сжатия изображения используйте пакет nodejs tinypng.

npm install --save tinify

Выполнить аутентификацию

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

Сжать файл

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

Вы также можете загрузить изображение из буфера (строка с двоичным кодом) и получить сжатые данные изображения.

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;
    // ...
  });
});

Вы можете делать много других удивительных манипуляций с изображениями. Ознакомьтесь с документацией здесь

person kiranvj    schedule 07.03.2018

Недавно я решил эту проблему для себя, используя пакет tinify, и обнаружил, что документации не хватает.

У меня есть внешний интерфейс Vue, собирающий загрузки файлов от пользователя с помощью vue2dropzone. Они отправляются на серверную часть node / Express. Мне нужно сжать файл и загрузить его в экземпляр S3 без сохранения на диске. Это означает использование мультипамяти. В результате не будет возможности использовать tinify.fromFile(), так как локального файла нет.

В промежуточном программном обеспечении моих изображений:

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);
   }
}

Затем в моем файле маршрутов:

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

// skipped several lines for brevity

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

Этот процесс создает загрузку multer singleFile в memoryStorage, делая файл доступным по адресу req.files.file[0] (req.files[“file”] , так как я указал “file” в качестве имени в полях multer, прокручивайте этот массив, если загрузка нескольких). После настройки я получаю имя файла, устанавливаю источник с помощью tinify для чтения из req.files.file[0].buffer в качестве буфера. Затем я устанавливаю источник на свой экземпляр s3 и отправляю общедоступную ссылку на файл.

Надеюсь, этот ответ поможет вам. Я определенно мог бы изменить процесс, чтобы изменить местонахождение файла или даже записать его на диск, изменив параметры мультиплексора.

person Brad Chandler    schedule 19.01.2021