Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

AngularJS file upload from ngThumb directive (with angular-file-upload)

I am using Angular-File-Upload to upload file to server. Everything works fine and the file can be saved in DB.

The question is, how can I load back the images that I saved when in edit mode?

This is the directive to create canvas when upload the pic

'use strict';

myApp

    .directive('ngThumb', ['$window', function($window) {
        var helper = {
            support: !!($window.FileReader && $window.CanvasRenderingContext2D),
            isFile: function(item) {
                return angular.isObject(item) && item instanceof $window.File;
            },
            isImage: function(file) {
                var type =  '|' + file.type.slice(file.type.lastIndexOf('/') + 1) + '|';
                return '|jpg|png|jpeg|bmp|gif|'.indexOf(type) !== -1;
            }
        };

        return {
            restrict: 'A',
            template: '<canvas/>',
            link: function(scope, element, attributes) {
                if (!helper.support) return;

                var params = scope.$eval(attributes.ngThumb);

                if (!helper.isFile(params.file)) return;
                if (!helper.isImage(params.file)) return;

                var canvas = element.find('canvas');
                var reader = new FileReader();

                reader.onload = onLoadFile;
                reader.readAsDataURL(params.file);

                function onLoadFile(event) {
                    var img = new Image();
                    img.onload = onLoadImage;
                    img.src = event.target.result;
                }

                function onLoadImage() {
                    var width = params.width || this.width / this.height * params.height;
                    var height = params.height || this.height / this.width * params.width;
                    canvas.attr({ width: width, height: height });
                    canvas[0].getContext('2d').drawImage(this, 0, 0, width, height);
                }
            }
        };
    }]);

This is an html snippet that load canvas when there is an upload:

<div class="table-responsive"  ng-hide="!uploaderImages.queue.length">
    <table class="table">
        <thead>
            <tr>
            <th width="50%">Name</th>
            <th ng-show="uploaderImages.isHTML5">Size</th>
            <th ng-show="uploaderImages.isHTML5">Progress</th>
            <th>Status</th>
            <th>Actions</th>
            </tr>
        </thead>
        <tbody>
          <tr ng-repeat="item in uploaderImages.queue">
          <td><strong>{{ item.file.name }}</strong>
            <div ng-show="uploaderImages.isHTML5" ng-thumb="{ file: item._file, height: 100 }"></div>
        </td>
        <td ng-show="uploaderImages.isHTML5" nowrap>{{ item.file.size/1024/1024|number:2 }} MB</td>
        <td ng-show="uploaderImages.isHTML5">
<div class="progress progress-xs margin-bottom-0">
<div class="progress-bar" role="progressbar" ng-style="{ 'width': item.progress + '%' }"></div>
</div></td>
<td class="text-center">
    <span ng-show="item.isSuccess"><i class="glyphicon glyphicon-ok"></i></span>
    <span ng-show="item.isCancel"><i class="glyphicon glyphicon-ban-circle"></i></span>
    <span ng-show="item.isError"><i class="glyphicon glyphicon-remove"></i></span>
</td>
<td nowrap>
<button type="button" class="btn btn-danger btn-xs" ng-click="item.remove()">
<span class="glyphicon glyphicon-trash"></span> Remove
</button></td>
</tr>
</tbody>
</table>
</div>

Thanks!!

like image 621
d3bug3r Avatar asked Sep 29 '15 09:09

d3bug3r


4 Answers

Since the uploader is working fine already and you're able to save the images into the database, all you need to do is to show the uploaded images as thumbnails on a canvas.

That can be done using some jQuery like this:

// source of a large image - replace this with the URL of the uploaded image (served from the database)
var IMAGE_SRC = "http://cdn-media-1.lifehack.org/wp-content/files/2014/09/activities-on-the-beach.jpg";

// set the height for the thumbnail - your uploader currently has 100
var height = 100;

function drawImage() {
  // create a new Image object
  var img = new Image();

  // set up the onLoad handler on the image object to draw the thumbnail into the canvas
  img.onload = function() {
    // calculate the thumbnail width for the fixed height above, respecting the image aspect ratio
    var width = this.width / this.height * height;

    // set the dimensions on the canvas
    $("canvas").attr({
      width: width,
      height: height
    });

    // draw the image from the loaded image object
    $("canvas")[0].getContext("2d").drawImage(img, 0, 0, width, height);
  };

  // set the source of the image object to the URL of the uploaded image (served from the database)
  img.src = IMAGE_SRC;
}

// Do all of this when the button is clicked
$("button").click(drawImage);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button>Load image into Canvas</button>
<br />
<br />
<canvas></canvas>

The same code could also be converted into another angular directive - something like <uploaded-image></uploaded-image>.

like image 141
Hari Pachuveetil Avatar answered Nov 09 '22 04:11

Hari Pachuveetil


Writing down a simple directive to preview the returned images is quite easy. More or less is the a simplified version of the ngThumb directive you have provided.

angular.module('components', [])
    .directive('imgPreview', [function () {
    return {
        restrict: 'E',
        template: '<canvas/>',
        replace: true,
        link: function (scope, element, attrs) {
            var myCanvas = element[0];
            var ctx = myCanvas.getContext('2d');
            var img = new Image;
            img.onerror = function () {
                throw new Error("Image can't be loaded");
            }
            img.onload = function () {
                myCanvas.width = img.width;
                myCanvas.height = img.height;
                ctx.drawImage(img, 0, 0); // Or at whatever offset you like
            };
            img.src = attrs.image;
        }
    }
}]);

Demo

like image 2
vorillaz Avatar answered Nov 09 '22 04:11

vorillaz


// source of a large image - replace this with the URL of the uploaded image (served from the database)
var IMAGE_SRC = "http://cdn-media-1.lifehack.org/wp-content/files/2014/09/activities-on-the-beach.jpg";

// set the height for the thumbnail - your uploader currently has 100
var height = 100;

function drawImage() {
  // create a new Image object
  var img = new Image();

  // set up the onLoad handler on the image object to draw the thumbnail into the canvas
  img.onload = function() {
    // calculate the thumbnail width for the fixed height above, respecting the image aspect ratio
    var width = this.width / this.height * height;

    // set the dimensions on the canvas
    $("canvas").attr({
      width: width,
      height: height
    });

    // draw the image from the loaded image object
    $("canvas")[0].getContext("2d").drawImage(img, 0, 0, width, height);
  };

  // set the source of the image object to the URL of the uploaded image (served from the database)
  img.src = IMAGE_SRC;
}

// Do all of this when the button is clicked
$("button").click(drawImage);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button>Load image into Canvas</button>
<br />
<br />
<canvas></canvas>
like image 2
Vishnu T Asok Avatar answered Nov 09 '22 06:11

Vishnu T Asok


If I understand your question right, then I think you need to upload a blob (so after editing an image in canvas you have a Data URI. And you need to convert this into a Blob which you can upload!

Here is the solution I used for uploading a cropped image with angular-file-upload:

https://github.com/nervgh/angular-file-upload/issues/208#issuecomment-116344239

You need to use

  • uploader.onBeforeUploadItem

to overwrite the actual file = item._file!

PS: There is also a function for converting 'DataURI' to 'Blob' in the given link!

like image 2
Betty St Avatar answered Nov 09 '22 05:11

Betty St