Sending a reduced size image to file upload

2177
10
Jump to solution
11-15-2016 10:57 AM
TomSellsted
MVP Regular Contributor

Greetings,

I have a mobile app that I have built using the JSAPI that allows the user to take a picture with their iPad and posts it to a geoprocessing upload service.  This is working very well, but the image size is unnecessarily large.  I have a couple of functions that reduce the image size and create a BLOB that I would like to post to the same geoprocessing upload service.  I have tried many different variations of posting the file using the request module in the JSAPI with no luck.

The request I make gives me a request succeeded message, but I can see in my ArcGIS Server logs that the request is actually failing (which is also odd...).  The error message says "Error performing upload operation, File size or type not supported for this service".  I am using the FormData which the documentation says will work, but I am obviously missing something.  Here is a snippet of the code that I am using to post the reduced size image.

var data = new FormData();
data.append('file', imageResized);
var photoRequest = esriRequest({
   url: url,
   form: data,
   content: { f: "json" },
   handleAs: "blob",
   load: requestSucceeded, // callback
   error: requestFailed // on error
});

I would appreciate any suggestions on what I am missing. 

Thanks very much!

Regards,

Tom

0 Kudos
1 Solution

Accepted Solutions
JohnGrayson
Esri Regular Contributor

Here's some code I found:

// using put-selector/put to create html node
var formNode = put("form",{"method":"post","enctype":"multipart/form-data"});
var formData = new FormData(formNode);
formData.append("file",arrayBuffer,filename);

View solution in original post

10 Replies
RobertScheitlin__GISP
MVP Esteemed Contributor

Tom,

   Where is the code that produces imageResized object?

0 Kudos
TomSellsted
MVP Regular Contributor

Robert,

Thanks very much for the quick reply.  Here is the code that I am using to reduce the image size:

var imageResized, imageDataUrl;

var dataURLToBlob = function(dataURL) {
     var BASE64_MARKER = ';base64,';
     if (dataURL.indexOf(BASE64_MARKER) == -1) {
          var parts = dataURL.split(',');
          var contentType = parts[0].split(':')[1];
          var raw = parts[1];

          return new Blob([raw], {type: contentType});
     }

     var parts = dataURL.split(BASE64_MARKER);
     var contentType = parts[0].split(':')[1];
     var raw = window.atob(parts[1]);
     var rawLength = raw.length;

     var uInt8Array = new Uint8Array(rawLength);

     for (var i = 0; i < rawLength; ++i) {
          uInt8Array[i] = raw.charCodeAt(i);
     }

     return new Blob([uInt8Array], {type: "image/jpg"});
     //return new Blob([uInt8Array], {type: contentType});
}

on(dom.byId("submitRequest"), "click", sendContent);

on(dom.byId('aPhoto'), 'change', function(evt) {
     // Read in file
     var file = evt.target.files[0];

     // Ensure it's an image
     if(file.type.match(/image.*/)) {
          console.log('An image has been loaded');

          // Load the image
          var reader = new FileReader();
          reader.onload = function (readerEvent) {
               var image = new Image();
               image.onload = function (imageEvent) {

                    // Resize the image
                    var canvas = document.createElement('canvas'),
                         max_size = 800,
                         width = image.width,
                         height = image.height;
                    if (width > height) {
                         if (width > max_size) {
                              height *= max_size / width;
                              width = max_size;
                         }
                    } else {
                         if (height > max_size) {
                              width *= max_size / height;
                              height = max_size;
                         }
                    }
                    canvas.width = width;
                    canvas.height = height;
                    canvas.getContext('2d').drawImage(image, 0, 0, width, height);
                    imageDataUrl = canvas.toDataURL('image/jpeg');
                    imageResized = dataURLToBlob(imageDataUrl);
               };
               image.src = readerEvent.target.result;
               evt.target.files[0] = readerEvent.target.result;
          };
          reader.readAsDataURL(file);
     }          
});

Regards,

Tom

0 Kudos
RobertScheitlin__GISP
MVP Esteemed Contributor

Tom,

   have you checked to see if the imageResized object is what you expected before you do the data.append?

0 Kudos
TomSellsted
MVP Regular Contributor

Robert,

I am able to draw the resized image back on the screen with the imageDataUrl variable, but I don't really have a way to know for sure if the BLOB that is created in the imageResized variable is valid.  I would think that a BLOB is a BLOB and either way I should be able to send it to the server.  

Regards,

Tom

0 Kudos
RobertScheitlin__GISP
MVP Esteemed Contributor

Tom,

   I first thought would be a timing issue as you sure that the object is ready when you send it to the form? Can you add a setTimeout to delay and see if that helps?

0 Kudos
TomSellsted
MVP Regular Contributor

Robert,

I am using the Chrome debugger and I can definitely see that the variable is loaded before I hit the upload button.  The resize takes less than a second on a 4M image.

Thanks very much!

Regards,

Tom

0 Kudos
JohnGrayson
Esri Regular Contributor

Assuming the file size and type are not the issue as reported by the server error log, is the request using "method":"POST" and "enctype":"multipart/form-data"?  When creating a FormData object I normally pass in a html <form> node that has these properties set, but I"m not sure if esriRequest(...) does this for you.  Also, when calling esriRequest(), "handleAs" specifies how the response is handled in your client code and not related to what you are sending.

0 Kudos
TomSellsted
MVP Regular Contributor

John,

Do you have an example of how you pass a html <form> node in a FormData object?

Regards,

Tom

0 Kudos
JohnGrayson
Esri Regular Contributor

Here's some code I found:

// using put-selector/put to create html node
var formNode = put("form",{"method":"post","enctype":"multipart/form-data"});
var formData = new FormData(formNode);
formData.append("file",arrayBuffer,filename);

View solution in original post