I have a question that may been easy for some to answer...
I have this Java method:
#RequestMapping(value = "/exportEditableFields", method = RequestMethod.GET)
#ResponseStatus(HttpStatus.OK)
#ResponseBody
public void exportEditableFields(
#RequestParam(value = "conversationId") final String conversationId,#RequestParam(
value = "schoolId") final Long schoolId,
#RequestParam(value = "schoolAbbreviation") final String schoolAbbreviation,
final HttpServletResponse response) throws IOException {
SimpleDateFormat dateFormat = new SimpleDateFormat("MM-dd-yyyy_hhmm");
School school = schoolService.getSchoolById(schoolId);
String fileName =
String.format("SDMS-%s-%s-Editable Fields-%s", school.getAbbreviation(), school.getName(),
dateFormat.format(new Date()));
response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
fileName = fileName + ".xlsx";
response.setHeader("Content-Disposition", "attachment; filename=\""
+ fileName + "\"");
BufferedOutputStream bos =
new BufferedOutputStream(response.getOutputStream());
XSSFWorkbook workbook = new XSSFWorkbook();
exportManager.writeFieldRecords(bos, schoolId);
FileOutputStream fos = new FileOutputStream(fileName);
workbook.write(fos);
fos.close();
bos.flush();
response.flushBuffer();
}
I am invoking this method using EXTJS this way:
listeners: {
click: function(){
Ext.Ajax.request({
disableCaching: false,
method: 'GET',
params: {
conversationId : this.conversationId,
schoolId : Ext.getStore('DataStore').getProxy().extraParams.schoolId,
schoolAbbreviation: Ext.getStore('DataStore').getProxy().extraParams.schoolAbbreviation
},
url: 'export/exportEditableFields',
success: function(r, opts) {
var resp = Ext.decode(r.responseText);
var b =1;
Ext.DomHelper.append(Ext.getBody(), {
tag: 'iframe',
frameBorder: 0,
width: 0,
height: 0,
css: 'display:none;visibility:hidden;height:0px;',
src: resp.downloadUrl
}); },
failure: function(response, opts) {
console.log('server-side failure with status code ' + response.status);
}
});
}
the problem is from the browser I can't download the xlsx that the java method generates.
Any idea ?
how i should process the success response to download the file?
I am using EXTJS 4.2, Tomcat 7, Java 7
thanks a lot!
Thanks all! The problem was solved using window.open(url, '_self');
For downloading a file in ExtJs, you have to use form.submit() instead of Ajax.It's target should be iframe
Related
I am trying to implement logic of download pdf from db on angular 5. I am facing issue in download file. File gets downloaded but throws error on opening -"Failed to load".
I have looked at so many blogs and question/answers but not able to find the mistake in my code.
In Database -> pdf file content saved as BLOB
Rest web service ->
In below code pdfData is the data from BLOB type column, which is byte[] in java code here
#GetMapping("downloadReport/{reportId}")
public StreamingResponseBody downloadDocument(byte[] pdfData) {
return outputStream -> {
//This way working for sample
/*try (InputStream inputStream = new ByteArrayInputStream(
Files.readAllBytes(Paths.get("D:/pdfWithoutPassword.pdf")))) {
IOUtils.copy(inputStream, outputStream);
}*/
//This way not working when data fetched from Database
try (InputStream inputStream = new ByteArrayInputStream(pdfData)) {
IOUtils.copy(inputStream, outputStream);
}
outputStream.close();
};
Angular 5 code
downloadReport(reportType: string, reportId: string) {
let fileDownloadUrl = environment.apiUrl + "/downloadReport" + "/" + reportId;
return this.httpClient
.get(fileDownloadUrl, { observe: 'response', responseType: "blob"})
.subscribe(response => this.saveFileToSystem(response.body)),
error => console.log("Error downloading the file."),
() => console.info("OK");
}
saveFileToSystem(input: any) {
const blob = new Blob([input], { type: 'application/octet-stream' });
saveAs(blob, "testingpdf1.pdf");
}
Looking for help in solving this. Thanks in advance!
Here another way I did it you you can change :
#RequestMapping(value = "/generateReport", method = RequestMethod.POST)
public ResponseEntity<byte[]> generateReport(){
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.parseMediaType("application/pdf"));
StringBuilder filename = new StringBuilder("MyPdfName").append(".pdf");
byte[] bytes = pdfGeneratorService.generatePDF();
headers.add("content-disposition", "inline;filename=" + filename.toString());
headers.setCacheControl("must-revalidate, post-check=0, pre-check=0");
ResponseEntity<byte[]> response = new ResponseEntity<byte[]>(bytes, headers, HttpStatus.OK);
return response;
}
Try this :
From your html page
YourPdf.pdf
From your js file
generatePdf() {
this.yourService.generatePdf()
.subscribe(pdf => {
let mediaType = 'application/pdf';
let blob = new
Blob([this.converterService.base64ToArrayBuffer(pdf.pdfByteArray)], { type: mediaType });
saveAs(blob, fileName);
}, err => {
console.log('Pdf generated err: ', JSON.stringify(err));
});
}
Your converter service:
import { Injectable } from "#angular/core";
#Injectable()
export class ConverterService {
base64ToArrayBuffer(base64) {
var binaryString = window.atob(base64);
var binaryLen = binaryString.length;
var bytes = new Uint8Array(binaryLen);
for (var i = 0; i < binaryLen; i++) {
var ascii = binaryString.charCodeAt(i);
bytes[i] = ascii;
}
return bytes;
}
}
My Controller to which the request is mapped-
I return the value from AJAX, to the controller-
$.ajax({
type: 'GET',
dataType: 'json',
contentType:"application/json",
url:"/Putty/downloadProcess/?param="+param
});
#RequestMapping(value = "/downloadProcess", method = RequestMethod.GET)
protected void download(#RequestParam("param") String value, HttpServletResponse response)
throws ServletException, IOException {
Properties prop = new Properties();
InputStream input = new FileInputStream("config.properties");;
prop.load(input);
System.out.println(value);
String path = prop.getProperty("path.MS1");
String filepath= path.concat(value);
System.out.println(filepath);
File downloadFile = new File(filepath);
FileInputStream inStream = new FileInputStream(downloadFile);
String mimeType = "application/octet-stream";
System.out.println("MIME type: " + mimeType);
// modifies response
response.setContentType(mimeType);
response.setContentLength((int) downloadFile.length());
// forces download
String headerKey = "Content-Disposition";
String headerValue = String.format("attachment; filename=\"%s\"", downloadFile);
response.setHeader(headerKey, headerValue);
System.out.println(response);
// obtains response's output stream
OutputStream outStream = response.getOutputStream();
byte[] buffer = new byte[4096];
int bytesRead = -1;
while ((bytesRead = inStream.read(buffer)) != -1) {
outStream.write(buffer, 0, bytesRead);
}
inStream.close();
outStream.close();
This displays the filenames on my JSP
<c:forEach var="listValue" items="${files}">
<label onClick="download('${listValue}')">${listValue}</label>
<br>
</c:forEach>
The problem is that, I can see the MIME type on my console, along with the value returned by AJAX- The filename. But I do not get the Download dialog box, when I click on the file names, displayed on my JSP. Am I not handling the requests properly or I am missing something else.
Thanks!
Try it
ServletOutputStream out = response.getOutputStream();
response.setContentType("application/octet-stream");
if (file.isFile())
{
response.setHeader("Content-Disposition", "attachment;filename=\"" + downloadFile.getName() + "\"");
try (FileInputStream inputStream = new FileInputStream(downloadFile ))
{
IOUtils.copy(inputStream, out);
}
}
The Open/Save dialogue appears by default so we can not force anything. It is a browser specific settings that you cant change on the client side.
For Mozilla Firefox example :
I've tried to open itext created pdf file using jsp code but not opening valid pdf file.
BTW if I'll open pdf in generated path then it is valid generated pdf.
<%
//code to generate pdf on file location.
String pdfurl = filePDF.getAbsolutePath();
File pdf = null;
try {
System.out.println("pdfurl : " + pdfurl);
response.setCharacterEncoding("utf-8");
pdf = new File(pdfurl);
response.setContentType("application/pdf");
response.setHeader("Expires", "0");
response.setHeader("Cache-Control", "must-revalidate, post-check=0, pre-check=0");
response.setHeader("Content-Disposition", "inline;filename=checklist.pdf");
response.setHeader("Accept-Ranges", "bytes");
response.setContentLength((int) pdf.length());
OutputStream sos = response.getOutputStream();
FileInputStream input = new FileInputStream(pdf);
BufferedInputStream buf = new BufferedInputStream(input);
int readBytes = 0;
while ((readBytes = buf.read()) != -1) {
sos.write(readBytes);
}
System.out.println("Finished writing bytes to output stream.");
sos.flush();
sos.close();
input.close();
} catch (Exception ex) {
ex.printStackTrace();
} finally {
if (null != pdf && pdf.exists() && !pdf.isDirectory()) {
try {
pdf.delete();
System.out.println("Deleted file from " + pdfurl + " successfully");
} catch (Exception ex) {
System.out.println("Error while deleting pdf from : " + pdfurl);
}
}
}
%>
And angularJS code for ajax call:
pfqa.createDocument = function(action,data){
$("body").addClass("loading");
var deferred = $q.defer();
var paramJsonObj= {
'userId' : userId,
};
var data = angular.copy(paramJsonObj);
data = angular.toJson(data);
$http({
url : 'services/downloadPDF.jsp',
dataType: 'json',
method : 'POST',
headers : {
'Content-type' : 'application/json',
},
data: {data: paramJsonObj},
responseType : 'arraybuffer'
}).success(function(data, status, headers, config) {
var file = new Blob([ data ], {
type : 'application/json'
});
var fileURL = URL.createObjectURL(file);
var a = document.createElement('a');
a.href = fileURL;
a.target = '_blank';
a.download = 'checklist.pdf';
document.body.appendChild(a);
a.click();
}).error(function(data, status, headers, config) {
});
$("body").removeClass("loading");
}
Please guide me what I'm missing here.
What you are missing here is :
Use : application/pdf instead of application/json
$http({
url : 'services/downloadPDF.jsp',
dataType: 'json',
method : 'POST',
headers : {
'Content-type' : 'application/pdf',
},
data: {data: paramJsonObj},
responseType : 'arraybuffer'
}).success(function(data, status, headers, config) {
var file = new Blob([ data ], {
type : 'application/pdf'
});
var fileURL = URL.createObjectURL(file);
var a = document.createElement('a');
a.href = fileURL;
a.target = '_blank';
a.download = 'checklist.pdf';
document.body.appendChild(a);
a.click();
}).error(function(err) {
console.log(err);
});
That's it !!!
The problem is next necessary to make file on server and after sending to client and print.
#RequestMapping(value = "/some", method = RequestMethod.GET)
public void getFileForPrint(HttpServletResponse response,
#RequestParam(value = "id", required = true) Long id,
#RequestParam(value = "print", defaultValue = "false") Boolean print) throws Exception {
response.setCharacterEncoding("UTF-8");
response.setHeader("Content-Disposition", "attachment; filename*=UTF-8''" + fname);
ServletOutputStream out = response.getOutputStream();
somefile.write(out);
Desktop.getDesktop.print(new File("download location browser"));}
}
If you mean by when you are hitting an end point you want to download a file immediately then the following code should help you.
#RequestMapping(value = "/somePath", method = RequestMethod.GET)
#ResponseBody
public void getFileForPrint(HttpServletResponse response,
#RequestParam(value = "id", required = true) Long id,
#RequestParam(value = "print", defaultValue = "false") Boolean print) throws Exception {
String filename="nameOfFileWhenDownloaded.txt";
try {
response.setContentType(MediaType.APPLICATION_OCTET_STREAM_VALUE);
response.setHeader("Content-Disposition", "attachment; filename=\"" + filename + "\"");
OutputStreamWriter osw = new OutputStreamWriter(response.getOutputStream());
osw.write(contentsOfTheFile);
osw.flush();
osw.close();
response.flushBuffer();
} catch (Exception e) {
e.printStackTrace();
throw new Exception("Error is sending file");
}
}
I´m trying to open a pdf that I have created using iText library in my browser, but it fails.
This is the code I´m using to send to browser
File file = new File(path);
try{
//InputStream stream=blob.getBinaryStream();
InputStream streamEntrada = new FileInputStream(file);
//ServletOutputStream fileOutputStream = response.getOutputStream();
PrintWriter print = response.getWriter();
int ibit = 256;
while ((ibit) >= 0)
{
ibit = streamEntrada.read();
print.write(ibit);
}
response.setContentType("application/text");
response.setHeader("Content-Disposition", "attachment;filename="+name);
response.setHeader("Pragma", "cache");
response.setHeader("Cache-control", "private, max-age=0");
streamEntrada.close();
print.close();
return null;
}
catch(Exception e){
return null;
}
}
I tried with FileOutputStream but isn´t works. I´m desperate.
Thank you.
Now, I´m trying this way, but it doesn´t work:
public class MovilInfoAction extends DownloadAction{
protected StreamInfo getStreamInfo(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
//Here the creation of the PDF
//Storing data
PdfData dPdf = pdf.drawPDF(terminal);
String path = dPdf.getPath();//Path
String name = dPdf.getName()+".pdf";//Pdf´s name
String contentType = "application/pdf";//ContentType
response.setContentType(contentType);
response.setHeader("Content-Disposition","attachment; filename="+name);
response.setHeader("Cache-control", "private, max-age=0");
response.setHeader("Content-Disposition", "inline");
File file = new File(path);
byte[] pdfBytes = es.vodafone.framework.utils.Utils.getBytesFromFile(file);
return new ByteArrayStreamInfo(contentType, pdfBytes);
}
protected class ByteArrayStreamInfo implements StreamInfo {
protected String contentType;
protected byte[] bytes;
public ByteArrayStreamInfo(String contentType, byte[] bytes) {
this.contentType = contentType;
this.bytes = bytes;
}
public String getContentType() {
return contentType;
}
public InputStream getInputStream() throws IOException {
return new ByteArrayInputStream(bytes);
}
}
}
You specify the mimetype as application/text, when it should be application/pdf.
You should set the Header and ContentType before you write the data.
And set the Content Type to application/pdf.
change
response.setContentType("application/text");
to
response.setContentType("application/pdf");
and if you want your pdf to open in browser then make following change
response.setHeader("Content-Disposition", "inline");
Put the filename in double quote "
response.setHeader("Content-Disposition","attachment; filename=\"" + attachmentName + "\"");
Android Default Browser requires GET Request. It does not understand POST Request and hence cannot download the attachment. You can send a GET request as by sending GET request, it resolved my problem. Android browser generates a GET request on its own and sends it back to server. The response received after second request will be considered final by the browser even if GET request is sent on first time by the servlet.