I'm trying to download a file:
import org.apache.commons.io.IOUtils;
#GetMapping("/file")
public void file(#RequestParam("path") String path, HttpServletResponse response) throws IOException {
InputStream inStream = fmService.downloadFile("https://" + path);
IOUtils.copy(inStream, response.getOutputStream());
response.flushBuffer();
}
But when I visit localhost:8080/file?path=/Documents... a download gets not triggered.
If I use a txt file in the path, then the content of it is shown to me in the browser, but when I'm using a pdf file nothing really happens. Having 200 response code but no download.
How can I use spring-boot to download the files?
And the next step would be to call this spring-boot api endpoint and download from an Angular frontend.
I think the output must be different too then or?
You need to set the following header so that the browser knows to download a file from the returned response instead of displaying on browser. See
https://github.com/gtiwari333/spring-boot-blog-app/blob/master/src/main/java/gt/app/modules/file/FileDownloadUtil.java
response.setHeader("Content-Disposition", "attachment; filename=" + "a.txt");
A working GetMapping:
#GetMapping
void d(HttpServletResponse r) throws IOException {
r.setHeader("Content-Disposition", "attachment; filename=" + "a.txt");
r.getOutputStream().print("ABCD");
r.getOutputStream().flush();
}
//Or return input stream:
#GetMapping("/is")
void d(HttpServletResponse r) throws IOException {
r.setHeader("Content-Disposition", "attachment; filename=" + "a.txt");
InputStream is = new ByteArrayInputStream("Some test string".getBytes()); //or any input stream
org.apache.commons.io.IOUtils.copy(is, r.getOutputStream());
r.getOutputStream().flush();
}
Downloading file from angular app:
This gets tricky and needs to be done in three steps:
a first call to get direct link to the file
render the link in anchor tag <a href=
have user click the link to do the file download
You can refer to this: https://blog.gtiwari333.com/2017/01/angularjs-download-file-from-server.html
Related
How to add a download link in HTML preview page using thymleaf java? I have added controller code for download and also html code which i tried. I need to refer download endpoint from the controller, So I have attached the code for download pdf. Download pdf has two scenarios as mentioned below(api/v1/download?s and api/v1/download?s=1). How do I interpret and refer this endpoint to create the download button based on user inpt(EX:api/v1/download?s=1), it needs to redirect to api/v1/download?s=1 and download the pdf via thymleaf html.
Download URL:
api/v1/download?s
api/v1/download?s=1
// html code
</div>
<a th:href="#{|/download|}">download</a>
<span>Download</span>
</a>
</div>
// download code
#GetMapping("/{id}/download")
public void download(#PathVariable(BaseEntity.ID) String id, #RequestParam(name = "s") String sensitive,
HttpServletResponse response) {
try {
Path file = Paths.get(profilePdfService.generatePdf(id, sensitive).getAbsolutePath());
if (Files.exists(file)) {
response.setContentType("application/pdf");
response.addHeader("Content-Disposition", "attachment; filename=" + file.getFileName());
Files.copy(file, response.getOutputStream());
response.getOutputStream().flush();
}
}
catch (Exception ex) {
ex.printStackTrace();
}
}
I'm attempting to serve local or proxy files via my Java application.
With something like this
#ResponseBody
#RequestMapping(value = "/file/{file}", method = RequestMethod.GET)
public void doGet(HttpServletRequest request, HttpServletResponse response,#PathVariable("file") String f) throws IOException {
String filename = URLDecoder.decode(f, "UTF-8");
File file = new File("resources/files/", filename);
response.setHeader("Content-Type", "video/mp4");
response.setHeader("Content-Length", String.valueOf(file.length()));
response.setHeader("Content-Disposition", "inline; filename=\"" + file.getName() + "\"");
Files.copy(file.toPath(), response.getOutputStream());
}
With an example URL such as
example.com/file/out2KP2_1.mp4
I'm getting the error:
Problem accessing /file/out2KP2_1.mp4. Reason:
resources\files\out2KP2_1 Caused by:
java.nio.file.NoSuchFileException: resources\files\out2KP2_1 at
sun.nio.fs.WindowsException.translateToIOException(WindowsException.java:79)
If I add a trailing / to the url and requestMapping, it works, but on iOS and a few other places the video player doesn't seem to like loading a file with a trailing slash so it doesn't suit my purposes.
Any help appriciated.
Thanks for the mark down. Take it you didn't know the answer!?
It's a problem with Spring, you have to add :.+ to the file URL variable
i.e. #RequestMapping(value = "/file/{file:.+}", method = RequestMethod.GET)
How do I force the browser to display the pdf instead of downloading ?
Here is the controller
#RequestMapping(value = "/preview.pdf", method = RequestMethod.GET)
protected String preivewSection(
HttpServletRequest request,
HttpSession httpSession,
HttpServletResponse response) {
try {
byte[] documentInBytes = getDocument();
response.setHeader("Content-Disposition", "inline; filename=\"report.pdf\"");
response.setDateHeader("Expires", -1);
response.setContentType("application/pdf");
response.setContentLength(documentInBytes.length);
response.getOutputStream().write(documentInBytes);
} catch (Exception ioe) {
} finally {
}
return null;
}
If you remove this line, the pdf will open in the browser itself.
response.setHeader("Content-Disposition", "inline; filename=\"report.pdf\"");
It looks like the above mentioned controller is all we need from the server side, the problem is the browser doesn't support viewing PDF files.
Use this google chrome browser not support preview It.
response.setHeader("Content-Disposition", "attachment; filename=" + file.getName());
But I changed this header as :
response.setHeader("Content-Disposition", "inline; filename=" + file.getName());
preview ok !
Because inline (default value, indicating it can be displayed inside the Web page, or as the Web page)
https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Disposition
after checking the response from the postman, if result like this will work on chrome
Content-Disposition: name="inline"; filename="XXX.pdf"
i think the questioner param less the "name="
Content-Disposition: inline; filename="XXX.pdf" (not working on chrome)
if not set Content-Disposition some framework will auto add a default become
Content-Disposition: name="attachment"; filename="f.txt" (not working on chrome)
some plugin auto add "form-data; "before the header become:
Content-Disposition: form-data;name="inline"; filename="XXX.pdf" (not working on chrome)
Actually, I have that functionality, I got a frame where I set the URL (ip:port/birt/preview?__report=report.rptdesign&__format=pdf¶meters...) and that frame renders the PDF file.
But I want that URL hidden...
I need return a PDF file with Spring MVC but that PDF is generated by another application.
This means I got another app (Eclipse Birt Engine) that I pass the parameters through of an URL (ip:port/birt/preview?__report=report.rptdesign&__format=pdf¶meters...) and it generates a PDF file, I need from my controller get that PDF and return it with Spring MVC. Could somebody help?
That would be like the below:
#Controller
#RequestMapping("/generateReport.do")
public class ReportController
#RequestMapping(method = RequestMethod.POST)
public void generateReport(HttpServletResponse response) throws Exception {
byte[] data = //read PDF as byte stream
streamReport(response, data, "my_report.pdf"));
}
protected void streamReport(HttpServletResponse response, byte[] data, String name)
throws IOException {
response.setContentType("application/pdf");
response.setHeader("Content-disposition", "attachment; filename=" + name);
response.setContentLength(data.length);
response.getOutputStream().write(data);
response.getOutputStream().flush();
}
}
PDF content is just bytes so you can just write the PDF content bytes to the HttpResponse output stream.
I'm using Phonegap with javascript and jquery. I've created a java servlet, it returns a pdf file. I can get de file correctly in a browser but I can't on Phonegap.
My code is this (javascript):
$.ajax({
type: "GET",
url: "http://x.x.x.x:xxxx/MyApp/PDF",
success: function(data, textStatus, request) {
alert("pdf OK");
window.open(data, "_system");
},
error: function(data, textStatus, request) {
alert("pdr error");
}
And here the servlet (this works fine from browser):
protected void doGet(HttpServletRequest req, HttpServletResponse response) throws ServletException, IOException {
try {
// Create PDF (this works fine)
String ruta = getServletContext().getRealPath(reportTemplateUrl);
InputStream resourceAsStream = new FileInputStream(ruta);
jasperDesign = JRXmlLoader.load(resourceAsStream);
jasperReport = JasperCompileManager.compileReport(jasperDesign);
jasperPrint = JasperFillManager.fillReport(jasperReport, null, new JRBeanCollectionDataSource(findReportData(name)));
File pdf = new File("output.pdf");
JasperExportManager.exportReportToPdfStream(jasperPrint, new FileOutputStream(pdf));
// Send PDF
response.setContentType("application/pdf");
response.addHeader("Content-Disposition", "attachment; filename=output.pdf");
response.setContentLength((int) pdf.length());
InputStream fileInputStream = new FileInputStream(pdf);
OutputStream responseOutputStream = response.getOutputStream();
int bytes;
while ((bytes = fileInputStream.read()) != -1) {
responseOutputStream.write(bytes);
}
System.out.println("CREATED!");
} catch (JRException e) {
e.printStackTrace();
}
This code is running on iPad with Phonegap and always I get the OK alert. From the iPad's browser I can donwload and read the pdf (I put the URL in the browser as a normal page) and all is OK.
I think the problem is the "data", from javascript, I don't know if I need to save the file first or how to do to show it...
And yes, I need use a servlet and ajax, the PDF is dynamic. I don't mind open it with internal or external browser, but I need to see it.
Thanks!
:)
Well, I solved this doing a GET call on javascript opening the url on a new browser:
window.open("http://.../PDF?id=id&name=name&...", "_blank");
Without ajax.
Thanks everyone