I am using Jhipster.
I am using docx4j to create a .docx file.
I want to download this .docx file from server to client.
But The file I download is corrupted.
On server side:
I generate my file and put it in a byte[]
WordprocessingMLPackage p = null;
...
File f = new File(filePath);
p.save(f);
byte[] stream = Files.readAllBytes(f.toPath());
I have tried to send it to the client in different format:
byte[]
byte[] encoded Base64
String
String encoded Base64
An example of what's look like my method:
// send back as String encoded in Base64
public ResponseEntity<FileDTO> getFile(@PathVariable Long id) throws URISyntaxException, IOException {
FileDTO result = fillRepository.findOne(id);
byte[] stream = FileUtil.getFile(id) // retrieve file as byte[]
byte[] encoded = Base64.encodeBase64(stream);
String encodedString = new String(encoded, "UTF-8");
result.setFile(encodedString);
return ResponseUtil.wrapOrNotFound(Optional.ofNullable(result));
}
On client side:
I retrieve my file as byte[] or String and I put it in a blob to be downloaded.
FileService.get({id: id}, function(result) {
var res = result.file;
// var res = Base64.decode(result.file);
vm.blob = new Blob([res], {type: 'data:attachment;charset=utf-8;application/vnd.openxmlformats-officedocument.wordprocessingml.document'});
vm.url = (window.URL || window.webkitURL).createObjectURL(vm.blob);
});
My service is declared like this:
(function() {
'use strict';
angular
.module('myApp')
.factory('FileService', FileService);
FileService.$inject = ['$resource', 'DateUtils'];
function FileService($resource, DateUtils) {
var resourceUrl = 'api/file/:id/generate';
return $resource(resourceUrl, {}, {
'get': {
method: 'GET',
responseType:'arraybuffer'
}});}})();
When I download the file word say:
"We're sorry. We can't open file.docx because we found a problem with its content."
And when I compare my original file and the one downloaded in notepad++ for example I see that binary content is not exactly the same like there was encode/decode issues...
Also the size are not the same:
Original file 13Ko
Downloaded file 18Ko
Could you help me on knowing how and why the file downloaded is corrupted.
I finally found a solution:
I directly send back the binary without convertion in the response. And access it with a window.location
I a new Rest Controller without annotation:@RequestMapping("/api")
@RestController
public class FileGenerationResource {
...
@GetMapping("/file/{id}")
@Timed
public void getFile(@PathVariable Long id, HttpServletResponse response) throws URISyntaxException, IOException {
FileInputStream stream = fileService.getFile(id);
response.setContentType("application/vnd.openxmlformats-officedocument.wordprocessingml.document");
response.setHeader("Content-disposition", "attachment; filename=test.docx");
IOUtils.copy(stream,response.getOutputStream());
stream.close();
}
}
The controller content:
(function() {
'use strict';
angular
.module('myApp')
.controller('MyController', MyController);
MyController.$inject = ['$timeout', '$scope', '$stateParams', '$uibModalInstance'];
function MyController ($timeout, $scope, $stateParams, $uibModalInstance) {
var vm = this;
vm.clear = clear;
vm.dwl = dwl;
function dwl (id) {
window.location = "http://localhost:8080/file/"+id;
vm.clear();
}
function clear () {
$uibModalInstance.dismiss('cancel');
}
}
})();