1

I have been trying to follow different posts on downloading a file sent from my Web API. So far I can get the file to come, it will open the download window and it will save. However, I cannot open it so something must be wrong somewhere.

Here is my AngularJS so far.

return $http({
            url: State.Endpoint + "/api/account/picture",
            method: "GET",
            responseType: 'arrayBuffer'
        }).then(function (data) {

            var octetStreamMime = 'application/octet-stream';
            var success = false;

            var file = new Blob([data.data], {
                type: "image/jpeg"
            });


            var fileUrl = URL.createObjectURL(file);

            var a = document.createElement('a');

            a.href = fileUrl;

            a.target = "_blank";

            a.download = "myFile.jpg";

            document.body.appendChild(a);

            a.click();


        });

That will make my successfully download the image for me. However, this doesn't let me open the file so either something is still wrong on client side or server side.

Server Side Code:

[Route("picture")]
    [HttpGet]
    public HttpResponseMessage GetPictureBlob()
    {
        HttpResponseMessage response = null;


        var localFilePath = HttpContext.Current.Server.MapPath("~/Content/Images/demo.jpg");

        if (!File.Exists(localFilePath))
        {
            response = Request.CreateResponse(HttpStatusCode.Gone);
        }
        else
        {

            var fStream = new FileStream(localFilePath, FileMode.Open, FileAccess.Read);
            // Serve the file to the client
            response = new HttpResponseMessage
            {
                StatusCode = HttpStatusCode.OK,
                Content = new StreamContent(fStream)
            };
            response.Content.Headers.ContentDisposition =
            new ContentDispositionHeaderValue("attachment")
            {
                FileName = Path.GetFileName(fStream.Name)
            };
            response.Content.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream");

            //response.Headers.Add("content-type", "application/octet-stream");

        }

        return response;

    }
georgeawg
  • 48,608
  • 13
  • 72
  • 95
Bailey Miller
  • 1,376
  • 2
  • 20
  • 36
  • What do you mean with `this doesn't let me open the file`? – lealceldeiro Feb 28 '17 at 19:58
  • When I go to open the file using paint, Photoshop, anything it doesn't display an image. – Bailey Miller Feb 28 '17 at 19:58
  • You mention downloading a file, do you mean displaying an image, cause that is what your code is doing... If you would like to download the image to the browser, then I would use a plugin for that called FileSaver, then you can simply save that file on the client side. Cheers! – TGarrett Feb 28 '17 at 20:03
  • Yes my goal is to provide the client with a file they are going to save to their local machine. – Bailey Miller Feb 28 '17 at 20:04

3 Answers3

1

I've done the very same thing with this code, where:

Code:

function downloadBlobFile(data, format, name) {
    // format must be one of https://developer.mozilla.org/en-US/docs/Web/API/Blob/type
    var file = new Blob([data], {type: 'application/' + format});
    file.lastModified = new Date();
    file.name = name + '.' + format.trim().toLowerCase();

    // guarantee IE compatibility
    if($window.navigator && $window.navigator.msSaveOrOpenBlob) {
        $window.navigator.msSaveOrOpenBlob(file, file.name);
    }
    //other web browser
    else {
        /**
         * Because this technology's specification has not stabilized, compatibility has been
         * checked here: https://developer.mozilla.org/en-US/docs/Web/API/URL/createObjectURL#Browser_compatibility
         */
        var fileURL = $window.URL.createObjectURL(file);

        /* trick for downloading the file, borrowed from:
         http://stackoverflow.com/questions/19327749/javascript-blob-filename-without-link
         */
        var a = angular.element("<a style='display: none;'/>").attr("href", fileURL).attr("download", file.name);
        angular.element(document.body).append(a);
        a[0].click();
        $window.URL.revokeObjectURL(fileURL);
        a.remove();
    }
}
lealceldeiro
  • 14,342
  • 6
  • 49
  • 80
  • This looks like a solid option, I need to go to another class but I am going to test this after I get back. – Bailey Miller Feb 28 '17 at 20:10
  • An *observation* here: As I've used this in a project along with _jQuery_ you'll find some code such `$("")` which you might want to replace with something like `document.getElementById('#myElementID')`, for instance, if you're not using _jQuery_. – lealceldeiro Feb 28 '17 at 20:15
  • OK, I just updated the answer in order to avoid the issue I commented before. – lealceldeiro Feb 28 '17 at 20:32
1

The provided value 'arrayBuffer' is not a valid enum value of type XMLHttpRequestResponseType.

Use arraybuffer all lowercase:

    $http({
        url: State.Endpoint + "/api/account/picture",
        method: "GET",
        //responseType: 'arrayBuffer'
        //USE arraybuffer lowercase
        responseType: 'arraybuffer'
        //OR
        //responseType: 'blob'
    })

When the responseType is not valid, the XHR API defaults to decoding the response as UTF-8. This corrupts binary files such as JPEG images.

For more information, see MDN XHR Web API - responseType.


Creating a Download Button

Instead of creating a <a download></a> element with JavaScript DOM manipulation, consider using the AngularJS framework.

This is an example of a Download button that becomes active after the data is loaded from the server:

<a download="data_{{files[0].name}}" xd-href="data">
  <button ng-disabled="!data">Download</button>
</a>

The xdHref Directive

app.module("myApp").directive("xdHref", function() {
  return function linkFn (scope, elem, attrs) {
     scope.$watch(attrs.xdHref, function(newVal) {
       if (newVal) {
         elem.attr("href", newVal);
       }
     });
  };
});

The DEMO on PLNKR.

georgeawg
  • 48,608
  • 13
  • 72
  • 95
  • Technically the first part on top of this answered my question. However, I really like the secondary answer in here. – Bailey Miller Mar 01 '17 at 14:07
  • The second part is for the benefit of readers searching for "angularjs save image file sent from web". Other readers might want an Angular solution. – georgeawg Mar 01 '17 at 15:55
1

 var a = document.createElement("a"); //Create <a>
    a.href = "data:image/png;base64," + ImageBase64;
    a.download = "Image.png"; //File name Here
    a.click(); //Downloaded file

Simplest way worked for me

Gautam Parmar
  • 686
  • 8
  • 18