8

I've got following issue and I can't find resolution. I created endpoint with Spring Boot and when I'm using Postman I'm getting response with image on body request.

But when I'm trying download and save file on computer using Angular and Blob and FileSaver my saved file is unable to read.

This is my angular controller:

vm.download = function (filename) {
    console.log("Start download. File name:", filename);
    $http.get('api/files/download/' + filename)
        .then(function (response) {
            console.log(data);
            var data = new Blob([response.data], {type: 'image/jpeg;charset=UTF-8'});
            FileSaver.saveAs(data, filename);
        })
}

and here's my endpoint:

@RequestMapping(value = "/files/download/{id:.*}", method = RequestMethod.GET)
@ResponseBody
@Timed
public void DownloadFiles(@PathVariable String id, HttpServletRequest request, HttpServletResponse response) throws IOException {

    MongoClient mongoClient = new MongoClient();
    DB mongoDB = mongoClient.getDB("angularspingproject");


    BasicDBObject query = new BasicDBObject();
    query.put("filename", id);

    GridFS fileStore = new GridFS(mongoDB, "fs");
    GridFSDBFile gridFSDBFile = fileStore.findOne(query);

    if (gridFSDBFile != null && id.equalsIgnoreCase((String) gridFSDBFile.getFilename())) {
        try {
            response.setContentType(gridFSDBFile.getContentType());
            response.setContentLength((new Long(gridFSDBFile.getLength()).intValue()));
            response.setHeader("content-Disposition", "attachment; filename=" + gridFSDBFile.getFilename());

            IOUtils.copyLarge(gridFSDBFile.getInputStream(), response.getOutputStream());
        } catch (IOException e) {
            throw new RuntimeException("IOError writting file to output stream");
        }
    }
}

My header:

Cache-Control: no-cache, no-store, max-age=0, must-revalidate
Content-Length: 316707
Content-Type: image/jpeg;charset=UTF-8
Pragma: no-cache
Server:Apache-Coyote/1.1
X-Application-Context : angularspingproject:8080
X-Content-Type-Options : nosniff
X-XSS-Protection: 1; mode=block
content-Disposition: attachment; filename=main_page.jpg

@Edit Problem resolved

    vm.download = function (filename) {
        $http.get('api/files/download/' + filename, {responseType:'blob'})
            .then(function (response) {
                console.log(response);
                var data = new Blob([response.data], {type: 'image/jpeg;charset=UTF-8'});
                FileSaver.saveAs(data, filename);
            })
    }

I added responseType: 'blob' to $http

0

2 Answers 2

1

I'd guess that you're not getting a byte array back from your $http.get call. Try adding:

vm.download = function (filename) {
var config = {headers: {
        'Accept': "image/jpeg"
    }
};
$http.get('api/files/download/' + filename, config).then(function (response)             { 
       var myBuffer= new Uint8Array( response.data );

    var data = new Blob([myBuffer], {type: 'image/jpeg;charset=UTF-8'});
    FileSaver.saveAs(data, filename);
        })
}
Sign up to request clarification or add additional context in comments.

3 Comments

Unfortunately it didn't help.
I just changed it. I had png instead of jpeg. That may be the issue.
I just added creating an array buffer. That's what Blob is expecting in the constructor.
0

I have a special download service in angular that works very well and simple:

(function () {
    angular.module('common')
        .factory('downloadService', ['$http', '$window', 'contentDispositionParser',
            function ($http, $window, contentDispositionParser) {
                return {
                    downloadFile: downloadFile
                };

                function downloadFile(url, request)
                {
                    $http({
                        url: url, 
                        method: 'GET',
                        params: request,
                        responseType: 'blob'
                    })
                    .success(function (data, status, headers, config){
                        var disposition = headers('Content-Disposition');
                        var filename = contentDispositionParser.getFileName(disposition);
                        $window.saveAs(data, filename); // This is from FileSaver.js
                    });
                }

            }]);
})();

Filesaver.js is from here. ContentDispositionParser you can use anything or write yourself, it's only used for getting the proper filename, since it is apparently not an easy task, but not directly connected to saving the file itself (you might add the name in js e.g.)

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.