0

I'm creating an architecture for a SPL (software production line) and I need to make things as easy as possible for the purpose of industrial productivity. The architecture is RESTful, Web API at the server side, Angular 2 & Material 2 at the client side in a nutshell.

I just have this question

Since I write the front-end and back-end, is it possible that in my forms which have file-upload control, I just get binary data from that file and send it to the server in JSON alongside other properties?

In other words, instead of multipart/form-data, I want to send something like this:

{  
   "title":"we in the garden",
   "tags":[  
      "family",
      "holidy"
   ],
   "file":" is it possible to include file's binary data here? "
}

If yes, what do I miss, If no, why not?

3
  • Have you tried converting the binary data to base64? Then it might be possible to include it in JSON. Commented Apr 1, 2017 at 14:19
  • 2
    Possibly helpful: stackoverflow.com/questions/1443158/… Commented Apr 1, 2017 at 14:21
  • Also, consider BSON. Commented Apr 1, 2017 at 14:22

1 Answer 1

1

Possible but not recommended

One can use the FileReader.readAsDataURL() API to bring the file into memory as a base64 encoded string.

  vm.previewFile = function() {
    readBase64(vm.files[0]).then(function(data) {
      vm.data = data;
    })
  }  

  function readBase64(file) {
    var reader  = new FileReader();
    var future = $q.defer();

    reader.addEventListener("load", function () {
      future.resolve(reader.result);
    }, false);

    reader.addEventListener("error", function (event) {
      future.reject(event);
    }, false);

    reader.readAsDataURL(file);

    return future.promise;
  }

The Demo on PLNKR.

However, base64 encoding is inefficient. Converting a binary file to a base64 encoded DOMstring (UTF-16) will take 266% more memory. The browser will likely crash with large video files.

It is more efficient to POST a file directly:

//RECOMMENDED
//Send binary file directly
var config = { headers: { "Content-Type": undefined },
               params: { filename: vm.files[0].name,
                         size: vm.files[0].size,
                         type: vm.files[0].type
                       } 
             );
$http.post(url, vm.files[0], config);

The $http service will use the XHR send method to stream the browser File object to the server.

<input type="file" files-input 
       ng-model="files" ng-change="previewFile()"
/>

The files-input directive:

app.directive("filesInput", function() {
  return {
    require: "ngModel",
    link: function postLink(scope,elem,attrs,ngModel) {
      elem.on("change", function() {
        ngModel.$setViewValue(elem[0].files);   
      });
    }
  };      
});
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.