How can i download the PDF file in spring mvc? - java

this is my file path
public final static String BOOKINGPDFFILE= "D:/Hotels/pdf/";
This below code is what I have written to download pdf from the above resource folder
Pdf="column name in database i used for storing in database"
#RequestMapping(value = "/getpdf/{pdf}", method = RequestMethod.GET)
public void getPdf(#PathVariable("pdf") String fileName, HttpServletResponse response,HttpServletRequest request) throws IOException {
try {
File file = new File(FileConstant.BOOKINGPDFFILE + fileName+ ".pdf");
Files.copy(file.toPath(),response.getOutputStream());
} catch (IOException ex) {
System.out.println("Contract Not Found");
System.out.println(ex.getMessage());
}
}

Here is the way, hope it help.
#RequestMapping(value = "/getpdf/{pdf}", method = RequestMethod.GET)
public void getPdf(#PathVariable("pdf") String fileName, HttpServletResponse response) throws IOException {
try {
File file = new File(FileConstant.BOOKINGPDFFILE + fileName+ ".pdf");
if (file.exists()) {
// here I use Commons IO API to copy this file to the response output stream, I don't know which API you use.
FileUtils.copyFile(file, response.getOutputStream());
// here we define the content of this file to tell the browser how to handle it
response.setContentType("application/pdf");
response.setHeader("Content-disposition", "attachment;filename=" + fileName + ".pdf");
response.flushBuffer();
} else {
System.out.println("Contract Not Found");
}
} catch (IOException exception) {
System.out.println("Contract Not Found");
System.out.println(exception.getMessage());
}
}

You may try something like this:
#RequestMapping(method = { RequestMethod.GET }, value = { "/downloadPdf" })
public ResponseEntity<InputStreamResource> downloadPdf()
{
try
{
File file = new File(BOOKINGPDFFILE);
HttpHeaders respHeaders = new HttpHeaders();
MediaType mediaType = MediaType.parseMediaType("application/pdf");
respHeaders.setContentType(mediaType);
respHeaders.setContentLength(file.length());
respHeaders.setContentDispositionFormData("attachment", file.getName());
InputStreamResource isr = new InputStreamResource(new FileInputStream(file));
return new ResponseEntity<InputStreamResource>(isr, respHeaders, HttpStatus.OK);
}
catch (Exception e)
{
String message = "Errore nel download del file "+idForm+".csv; "+e.getMessage();
logger.error(message, e);
return new ResponseEntity<InputStreamResource>(HttpStatus.INTERNAL_SERVER_ERROR);
}
}
And in your web page you can write the link in this way:
download PDF

You need to create an implementation of AbstractPdfView to achieve this.. You can refer this link https://www.mkyong.com/spring-mvc/spring-mvc-export-data-to-pdf-file-via-abstractpdfview/

Here is the Detailed answer for your question.
let me start with the server side code:
Below class is used to create pdf with some random content and return the equivalent byte array outputstream.
public class pdfgen extends AbstractPdfView{
private static ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
public ByteArrayOutputStream showHelp() throws Exception {
Document document = new Document();
// System.IO.MemoryStream ms = new System.IO.MemoryStream();
PdfWriter.getInstance(document,byteArrayOutputStream);
document.open();
document.add(new Paragraph("table"));
document.add(new Paragraph(new Date().toString()));
PdfPTable table=new PdfPTable(2);
PdfPCell cell = new PdfPCell (new Paragraph ("table"));
cell.setColspan (2);
cell.setHorizontalAlignment (Element.ALIGN_CENTER);
cell.setPadding (10.0f);
//cell.setBackgroundColor (new BaseColor (140, 221, 8));
table.addCell(cell);
ArrayList<String[]> row=new ArrayList<String[]>();
String[] data=new String[2];
data[0]="1";
data[1]="2";
String[] data1=new String[2];
data1[0]="3";
data1[1]="4";
row.add(data);
row.add(data1);
for(int i=0;i<row.size();i++) {
String[] cols=row.get(i);
for(int j=0;j<cols.length;j++){
table.addCell(cols[j]);
}
}
document.add(table);
document.close();
return byteArrayOutputStream;
}
}
Then comes the controller code : here the bytearrayoutputstream is converted to bytearray and sent to the client side using the response-entity with appropriate headers.
#RequestMapping(path="/home")
public ResponseEntity<byte[]> render(HttpServletRequest request , HttpServletResponse response) throws IOException
{
pdfgen pg=new pdfgen();
response.setContentType("application/pdf");
response.setHeader("Content-Disposition", "attachment:filename=report.pdf");
byte[] contents = null;
try {
contents = pg.showHelp().toByteArray();
}
catch (Exception e) {
e.printStackTrace();
}
//These 3 lines are used to write the byte array to pdf file
/*FileOutputStream fos = new FileOutputStream("/Users/naveen-pt2724/desktop/nama.pdf");
fos.write(contents);
fos.close();*/
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.parseMediaType("application/pdf"));
//Here you have to set the actual filename of your pdf
String filename = "output.pdf";
headers.setContentDispositionFormData(filename, filename);
headers.setCacheControl("must-revalidate, post-check=0, pre-check=0");
ResponseEntity<byte[]> respons = new ResponseEntity<byte[]>(contents, headers, HttpStatus.OK);
return respons;
}
The header should be set to "application/pdf"
Then comes the client side code :
Where you can make ajax request to server to open the pdf file in new tab of the browser
$.ajax({
url:'/PDFgen/home',
method:'POST',
cache:false,
xhrFields: {
responseType: 'blob'
},
success: function(data) {
//alert(data);
let blob = new Blob([data], {type: 'application/pdf'}); //mime type is important here
let link = document.createElement('a'); //create hidden a tag element
let objectURL = window.URL.createObjectURL(blob); //obtain the url for the pdf file
link.href = objectURL; // setting the href property for a tag
link.target = '_blank'; //opens the pdf file in new tab
link.download = "fileName.pdf"; //makes the pdf file download
(document.body || document.documentElement).appendChild(link); //to work in firefox
link.click(); //imitating the click event for opening in new tab
},
error:function(xhr,stats,error){
alert(error);
}
});

Try this
#Controller
#RequestMapping("/download")
public class FileDownloadController
{
#RequestMapping("/pdf/{fileName}")
public void downloadPDFResource( HttpServletRequest request,
HttpServletResponse response,
#PathVariable("fileName") String fileName)
{
//If user is not authorized - he should be thrown out from here itself
//Authorized user will download the file
String dataDirectory = request.getServletContext().getRealPath("/WEB-INF/downloads/pdf/");
Path file = Paths.get(dataDirectory, fileName);
if (Files.exists(file))
{
response.setContentType("application/pdf");
response.addHeader("Content-Disposition", "attachment; filename="+fileName);
try
{
Files.copy(file, response.getOutputStream());
response.getOutputStream().flush();
}
catch (IOException ex) {
ex.printStackTrace();
}
}
}
}

Related

How to send PDF file on response

I'm trying to write a web app that converts images to PDF file. The user sends a couple of images (JPEG, PNG) and should receive and download a PDF file.
The main problem, for now, is that I don't know how to return the PDF file back to the client.
Here is my controller:
#PostMapping(path = "/upload",
consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
public void uploadFiles(#RequestParam("files") MultipartFile[] files) throws IOException {
imageToPdfConversionService.convert(files);
}
This is the service that converts images to PDF file (here I'm using itextpdf library):
public void convert(MultipartFile[] files) throws IOException {
List<ImageData> imagesData = Arrays.stream(files)
.map(file -> {
try {
return ImageDataFactory.create(file.getBytes());
} catch (IOException e) {
throw new RuntimeException(e);
}
})
.collect(Collectors.toList());
// PdfDocument pdfDocument = new PdfDocument(new PdfWriter("ImageToPdf.pdf"));
FileOutputStream fileOutputStream = new FileOutputStream("letspdf-server/src/main/resources/documents/file.pdf");
PdfDocument pdfDocument = new PdfDocument(new PdfWriter(fileOutputStream));
Document document = new Document(pdfDocument);
for (ImageData image : imagesData) {
Image img = new Image(image);
img.setWidth(pdfDocument.getDefaultPageSize().getWidth() - 50);
img.setAutoScaleHeight(true);
document.add(img);
pdfDocument.addNewPage();
}
pdfDocument.close();
}
Also, maybe store a PDF file somewhere and create a 'Download' button on the client-side when a file is generated to download the file from storage?
So first of all you need to change your api to return ResponseEntity and convert your resulted pdf into byte array. I'll attach a code snippet as an example
public static ResponseEntity<Resource> makeResponse(byte[] file, String filename, MultiValueMap<String, String> customHeaders) {
MediaType mediaType = MediaType.APPLICATION_OCTET_STREAM;
HttpHeaders headers = new HttpHeaders();
if (StringUtils.isNotEmpty(filename)) {
try {
mediaType = MediaType.valueOf(MIME_TYPES.detect(filename));
} catch (Exception var6) {
}
ContentDisposition contentDisposition = ContentDisposition.builder("attachment").filename(filename, StandardCharsets.UTF_8).build();
headers.setAccessControlExposeHeaders(ACCESS_CONTROL_EXPOSE_HEADERS);
headers.setContentDisposition(contentDisposition);
}
if (customHeaders != null && !customHeaders.isEmpty()) {
headers.addAll(customHeaders);
}
ByteArrayResource body = null;
if (file != null) {
body = new ByteArrayResource(file);
}
return ((BodyBuilder)ResponseEntity.ok().headers(headers)).contentType(mediaType).body(body);
}

when i write a code for download pdf but only one pdf is download(bcz this pdf is text only) another pdf is not open on spring boot and angular 12

enter image description here
enter image description here
Controller on spring boot--->
#PostMapping(value = "/getpdfs")
public void getSchemeNotes(HttpServletRequest request, #RequestBody String requestBody,HttpServletResponse response) {
MessageLogger.debug(logger, String.format("getSchemeIpoNote(requestBody = %s)", requestBody));
Map<String, String> query = Utility.getQueryParameters(request);
try {
Scheme scheme = (Scheme) DataParsingUtility.convertJsonStringtoObject(requestBody, Scheme.class);
String fileNames= scheme.getSchemeNote();
//String fileNames = "Campus Activewear Limited - IPO Note Apr'2022-compressed.pdf";
String outputPath = ParameterConfiguration.getUploadDirectory() + File.separator + fileNames;
MessageLogger.debug(logger, String.format("fileNames(fileNames = %s)", fileNames));
MessageLogger.debug(logger, String.format("outputPath(outputPath = %s)", outputPath));
InputStream is = null;
try {
is = new FileInputStream(new File(outputPath));
response.setHeader("Content-Disposition", "attachment;filename=\""+fileNames+"\"");
response.setHeader(Constants.FILE_NAME, fileNames);
response.setHeader( "application","blob");
IOUtils.copy(is, response.getOutputStream());
response.flushBuffer();
}
finally {
if (is != null) {
is.close();
}
}
} catch (Exception ex) {
MessageLogger.debug(logger, "Error while getting Scheme Note file!", ex);
}
}
angular controller-->
viewNote(obj: any) {
var reqData = {
"schemeNote" : obj
}
this.schemeService.getSchemeNote(null, reqData, (rsp) => {
this.messageLoggerService.debug("request>>>"+JSON.stringify(reqData));
this.messageLoggerService.debug("response>>>>"+rsp);
this.commonService.processDownloadResponse(rsp);
});
}

How get instance of HttpServletResponse for download files with JAVA EE

I have a file txt on the server (previously generated). When user clicks on button it generates the file, now I want (additionally) download the file inside my function. But I can't make it work(I'm new on JAVA EE), cause I don't know how to get HttpServletResponse.
From web I call function with this:
#Path("getreport")
#POST
#Consumes(MediaType.APPLICATION_JSON)
#Produces(MediaType.APPLICATION_JSON)
public JSONObject getreport(CommonInput input) {
JSONObject j = objectmapper.conertValue(reportBean.getreport(),JSONObject.class);
return j;
}
reprotBean has function:
public void getreport() {
//...doing many things
//generating my file
List<String> lines = new ArrayList<>();
lines.add("star file");
//..adding many lines
Path file = Paths.get("C:\\Users\\myuser\\file.txt");
Files.write(file, lines, StandardCharsets.UTF_8);
downloadFile();
//...doing many things
}
I found this way to download my file:
public void downloadFile(HttpServletResponse response){
String sourceFile = ""C:\\Users\\myuser\\file.txt"";
try {
FileInputStream inputStream = new FileInputStream(sourceFile);
String disposition = "attachment; fileName=outputfile.txt";
response.setContentType("text/txt");
response.setHeader("Content-Disposition", disposition);
response.setHeader("content-Length", String.valueOf(stream(inputStream, response.getOutputStream())));
} catch (IOException e) {
logger.error("Error occurred while downloading file {}",e);
}
}
private long stream(InputStream input, OutputStream output) throws IOException {
try (ReadableByteChannel inputChannel = Channels.newChannel(input); WritableByteChannel outputChannel = Channels.newChannel(output)) {
ByteBuffer buffer = ByteBuffer.allocate(10240);
long size = 0;
while (inputChannel.read(buffer) != -1) {
buffer.flip();
size += outputChannel.write(buffer);
buffer.clear();
}
return size;
}
}
When I try to use downloadFile(), it requires HttpServletResponse, and I don't have that parameter. I can't understand how to get that (how it works), or do I have to use another method for download my file?
All solutions I found requires HttpServletResponse (download files from browsers)
If you have that file generated already. Just need write it to HttpServletResponse
resp.setContentType("text/plain");
resp.setHeader("Content-disposition", "attachment; filename=sample.txt");
try(InputStream in = req.getServletContext().getResourceAsStream("sample.txt");
OutputStream out = resp.getOutputStream()) {
byte[] buffer = new byte[ARBITARY_SIZE];
int numBytesRead;
while ((numBytesRead = in.read(buffer)) > 0) {
out.write(buffer, 0, numBytesRead);
}
}
Be sure to make your file to be accessed by ServeletContext
If you are using Spring Rest framework. Can refer to below
#GetMapping("/download")
public ResponseEntity<byte[]> downloadErrorData() throws Exception {
List<Employee> employees = employeeService.getEmployees();
ObjectMapper objectMapper = new ObjectMapper();
String json = objectMapper.writeValueAsString(employees);
byte[] isr = json.getBytes();
String fileName = "employees.json";
HttpHeaders respHeaders = new HttpHeaders();
respHeaders.setContentLength(isr.length);
respHeaders.setContentType(new MediaType("text", "json"));
respHeaders.setCacheControl("must-revalidate, post-check=0, pre-check=0");
respHeaders.set(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=" + fileName);
return new ResponseEntity<byte[]>(isr, respHeaders, HttpStatus.OK);
}
credit to: https://www.jeejava.com/file-download-example-using-spring-rest-controller/

Java export Excel by browser

I want to export Excel by browser. If I click the export button I can see information in Chrome network, but it did not download. I can download excel to my project folder, but how to export excel through the browser? Below the Ajax and controller codes.
This is my Excel util:
public class WriteExcel {
/**
* #param answerList
* #return
*/
public static void writeData(List<Answer> answerList, String paperName, HttpServletResponse response) throws IOException {
Workbook workbook = new HSSFWorkbook();
Sheet sheet = workbook.createSheet("test");
for(int i=0; i<answerList.size();i++){
Answer answer = answerList.get(i);
Row row = sheet.createRow(i);
Cell cell = row.createCell(0);
cell.setCellValue(answer.getAnswerpname());
List<AnswerReceive> answerReceives = JSON.parseArray(answer.getAnswerdata(), AnswerReceive.class);
for(int j=0; j<answerReceives.size(); j++){
AnswerReceive answerReceive = answerReceives.get(j);
Cell tmp_cell = row.createCell(j+1);
tmp_cell.setCellValue(answerReceive.getData());
}
}
response.setContentType("application/octet-stream;charset=UTF-8");
response.setHeader("Content-Disposition", "attachment;filename="
.concat(String.valueOf(URLEncoder.encode(paperName, "UTF-8"))));
OutputStream out = response.getOutputStream();
workbook.write(out);
}
}
My controller:
#PostMapping("/export")
#ResponseBody
public Object exportExcel(#RequestParam("paperId") String paperId, HttpServletResponse response) throws IOException {
List<Answer> answerList = answerService.getData(paperId);
WriteExcel.writeData(answerList, "test", response);
}
My Ajax:
$("button[name='export']").click(function () {
$.ajax({
url: "/export",
type: "post",
data: {"paperId":$(this).attr("data-paper-id")},
success: function (data) {
console.log(data.flag);
console.log(data.Message);
}
})
})
Try following:
But you Apaches FileUtils for it
#PostMapping("/export", produdes = MediaType.APPLICATION_JSON_VALUE)
#ResponseBody
public Object exportExcel(#RequestParam("paperId") String paperId, HttpServletResponse response) throws IOException {
List<Answer> answerList = answerService.getData(paperId);
InputStream excelFile = WriteExcel.writeData(answerList, "test", response);
response.setHeader("Content-Disposition", "attachment; filename=Export" + LocalDate.now() + ".xlsx");
response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
FileCopyUtils.copy(excelFile, response.getOutputStream());
response.flushBuffer();
}
To create an Inputstream, attach to your writeData Funcion:
ByteArrayInputStream bais = null;
try {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
workbook.write(baos);
baos.flush();
byte[] buffer = baos.toByteArray();
bais = new ByteArrayInputStream(buffer);
baos.close();
} catch (IOException e) {
e.printStackTrace();
}
return bais;
you button should be somethin like this
<button target='_blank' href='/export'>
on server I would make this
response.contentType = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
response.addHeader(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=exceptions.xlsx")
response.flushBuffer();
Look at Download File Using Javascript/jQuery
Actually, if your headers are specified correctly, your file download should be started after clicking given element with corresponding href (in new tab) below code for starting download in the same tab.
I would recomend to use tools like that
http://jqueryfiledownload.apphb.com.
or through axios
axios.post("/yourUrl"
, data,
{responseType: 'blob'}
).then(function (response) {
let fileName = response.headers["content-disposition"].split("filename=")[1];
if (window.navigator && window.navigator.msSaveOrOpenBlob) { // IE variant
window.navigator.msSaveOrOpenBlob(new Blob([response.data], {type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'}),
fileName);
} else {
const url = window.URL.createObjectURL(new Blob([response.data], {type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'}));
const link = document.createElement('a');
link.href = url;
link.setAttribute('download', response.headers["content-disposition"].split("filename=")[1]); //you can set any name(without split)
document.body.appendChild(link);
link.click();
}
}
);

Post image with jQuery to Spring java as MultipartFile

I'm trying to send image to my server to store it to mysql database.
I'm trying to post Formdata with jQuery and receive it like a java MultipartFile and convert it to bytes[]. I found a few ways to do it , but neither is working,
can somebody help me please?
This is my best try:
<form>
<input type="file" id="file"/>
<a onclick="uploadImage()" >Upload</a>
</form>
JS
function uploadImage() {
var formData = new FormData();
formData.append('file', $('#file')[0].files[0]);
$.ajax({
type : 'POST',
url : '/admin/uploadImage',
headers : {
"X-CSRF-TOKEN" : token
},
data : formData,
cache: false,
contentType: false,
processData: false,
});
alert("proso");
}
and JAVA
#RequestMapping(value = "/uploadImage", method = RequestMethod.POST)
public void save(#RequestParam("file") MultipartFile file)
{
try
{
File convFile = new File(file.getOriginalFilename());
convFile.createNewFile();
System.out.println("file: " + convFile.getTotalSpace());
byte[] bFile = new byte[(int) convFile.length()];
FileInputStream fileInputStream = new FileInputStream(convFile);
fileInputStream.read(bFile);
fileInputStream.close();
Files newFile = new Files();
newFile.setFileName("4h");
newFile.setData(bFile);
filesRepository.save(newFile);
}
catch (IOException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
}
Can anybody help me?
Try following code
#RequestMapping(value = "/uploadImage", method = RequestMethod.POST)
public void save(MultipartHttpServletRequest request)
{
try
{
Iterator<String> itr = request.getFileNames();
while(itr.hasNext()) {
MultipartFile file = request.getFile(itr.next());
if(file != null) {
File convFile = new File(file.getOriginalFilename());
convFile.createNewFile();
System.out.println("file: " + convFile.getTotalSpace());
byte[] bFile = new byte[(int) convFile.length()];
FileInputStream fileInputStream = new
FileInputStream(convFile);
fileInputStream.read(bFile);
fileInputStream.close();
Files newFile = new Files();
newFile.setFileName("4h");
newFile.setData(bFile);
filesRepository.save(newFile);
}
}
catch (IOException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}

Categories

Resources