Search code examples
angularjshttpblobmultipartform-datadocverter

uploading text blob as file using $http or $resource with angular.js - mimicking curl style multipart/form upload


So I need to: upload a text blob as a file using $http or $resource with angular.js - mimicking curl style multipart/form upload.

There is a previous post on this problem i'm going to try to be more explicit about the issue with hopes that someone can identify where I may be going astray.

Here is an example of the curl command that I know works with this service:

curl \
http://c.docverter.com/convert \
-F from=markdown \
-F to=pdf \
-F input_files[]=@<(echo hello) #or @example.md for a file

previous post on this problem

example successful log response from sinatra

{"input_files"=>[{:filename=>"api.md", :type=>"text/markdown", :name=>"input_files[]", :tempfile=>#<Tempfile:/tmp/RackMultipart20160426-3-5tb8po>, :head=>"Content-Disposition: form-data; name=\"input_files[]\"; filename=\"api.md\"\r\nContent-Type: text/markdown\r\n"}], "from"=>"markdown", "to"=>"pdf"}

On to what I need to do

I need to upload markdown text (I assume using a blob) as a "file" - I have tried both $resource and $http with a dozen different configurations and no luck.

A typical miserable log response after my hundredth angular attempt:

{"from"=>"markdown", "input_files"=>["{}"], "to"=>"pdf"}

code example:

angular.module('app')
  .factory('convert', function ($resource) {
    return $resource('http://c.docverter.com/convert', null, {
    pdf: {
      method: 'POST',
      headers: { 'Content-Type': 'multipart/form-data' },
      params: {
        from: 'markdown',
        to: 'pdf',
        'input_files[]': new Blob(['##title'], 'text/markdown')
      }
    }
  });
});

This is really only one example of what i've tried. I've been hammering at this for a few hours and haven't had much luck so, perhaps someone on here knows more about multipart form data and can shed some light on the pitfalls of blobs and angular.


Solution

  • Ok a good nights sleep and another hour at it and I have a working upload and download:

    var fd = new FormData();
    var blob = new Blob([$scope.markdown], {type: 'text/markdown'});
    var file = new File([blob], "abc.md");
    fd.append('input_files[]', file);
    fd.append('from', 'markdown');
    fd.append('to', 'pdf');
    
    $http.post('https://mydocverterserver.com/convert', fd, {
        transformRequest: angular.identity,
        headers: {'Content-Type': undefined},
        responseType: 'arraybuffer'
    })
    .success(function(response){
      var b = new Blob([response], { type: 'application/vnd.openxmlformats-officedocument.wordprocessingml.document' });
      FileSaver.saveAs(b, 'abc.docx');
    })
    .error(function(res){
      console.log(res);
    });
    

    Still a little crude - i'll probably clean it up and move it to a factory, but it works.

    This is a docx but it works for markdown and pdf as well.

    The FileSaver bit comes from: angular-file-saver

    If you are looking for a docverter specific solution like I was - I explain the server side fix here