web-dev-qa-db-fra.com

Téléchargement et enregistrement de fichiers depuis le serveur à l'aide d'AngularJS

J'ai le problème suivant et je ne trouve pas de résolution. J'ai créé un point de terminaison avec Spring Boot et lorsque j'utilise Postman je reçois une réponse avec une image sur la demande du corps.

Mais lorsque j'essaie de télécharger et d'enregistrer un fichier sur un ordinateur à l'aide de Angular et Blob and FileSaver, mon fichier enregistré est incapable de lire.

Ceci est mon angular:

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);
        })
}

et voici mon point final:

@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");
        }
    }
}

Mon en-tête:

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 Problème résolu

    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);
            })
    }

J'ai ajouté responseType: 'blob' à $ http

8
Michał Styś

Je suppose que vous ne récupérez pas un tableau d'octets à partir de votre appel $ http.get. Essayez d'ajouter:

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);
        })
}
1
Mike Feltman

J'ai un service de téléchargement spécial en angular qui fonctionne très bien et simplement:

(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 vient de ici . ContentDispositionParser vous pouvez utiliser n'importe quoi ou écrire vous-même, il n'est utilisé que pour obtenir le nom de fichier approprié, car ce n'est apparemment pas une tâche facile, mais pas directement lié à l'enregistrement du fichier lui-même (vous pouvez ajouter le nom dans js par exemple)

0