Reputation: 308
I have small web application, which collects data from form, sends it via Ajax to spring boot server. Server generates pdf file and sends it back as byte array. Then I want a PDF to be opened in new tab butI see empty PDF there and that is my problem. This is the Ajax method:
function sendJson(json) {
$.ajax({
url: "/pdf/create",
type: "POST",
data: json,
contentType: "application/json",
success: function (data) {
alert('Success');
openFile(data)
},
error: function (e) {
console.log('Was trying to send data, but error occurred. ' + json);
alert('Error sending data to server');
}
});
}
Then I create a blob from data received and open it.
function openFile(byte) {
var file = new Blob([byte], {type: "application/pdf"});
var fileURL = URL.createObjectURL(file);
window.open(fileURL);
}
This is my spring boot controller:
@PostMapping(value = "/pdf/create")
public ResponseEntity<?> preparePdf(@RequestBody String data) throws IOException {
System.out.println("Data input: " + data);
ObjectMapper mapper = new ObjectMapper();
Map<String, Object> dataObject = mapper.readValue(data, Map.class);
try {
return pdfService.createPdfFromTemplate(dataObject);
} catch (Exception e) {
e.printStackTrace();
return ResponseEntity.badRequest().body(HttpStatus.BAD_REQUEST);
}
}
Processing goes here:
public ResponseEntity<Resource> createPdfFromTemplate(Map<String, Object> dataObject) throws IOException {
// data saved to DB. PDF is generated and saved locally
String filename = "generated_file.pdf";
File pdf = new File(filename);
byte[] fileBytes = FileUtils.readFileToByteArray(pdf);
ResponseEntity.BodyBuilder res = ResponseEntity.ok()
.contentType(MediaType.APPLICATION_OCTET_STREAM);
return res.body(new ByteArrayResource(fileBytes));
}
The text in generated pdf is cyrillic but I don't think the problem lies here, or some encoding. I think I'm missing something important here. Sometimes I see opinions that it can't be done via ajax or POST method is not a good way, but it seems logical to send json data and receive generated file back. Any ideas appreciated guys.
Upvotes: 1
Views: 917
Reputation: 308
Hope it will be useful for someone. I encoded my byte array into base64 String on server side using Base64.getEncoder().encodeToString(fileBytes)
as a body to my response. In JS before opening a file I converted it to ArrayBuffer like this:
function base64ToArrayBuffer(base64) {
var binaryString = window.atob(base64);
var binaryLen = binaryString.length;
var bytes = new Uint8Array(binaryLen);
for (var i = 0; i < binaryLen; i++) {
bytes[i] = binaryString.charCodeAt(i);
}
return bytes;
}
And file is opened in a new tab as I expected.
Upvotes: 1