CXF JAX-RS downloading resource from URL - java

I want to send across resource(say a image) from some URL to front-end.
The typical way of doing this is to create a File and build the response. Is there any way in which I don't have to create the File in java code and still send the resource to front-end.
Front-end cannot access the URL due to some constraints.
Currently the Pseudo code looks like this.
File file = new File(fullPath);
FileUtils.copyURLToFile(url, file);
ResponseBuilder response = Response.ok(modulePDF);
I want to send content of URL to front-end without creating file. Is there any way?

What way did have in mind to actually obtain the file without creating a File object?
Not sure I fully understand the complete requirement, but you don't have to create a File object. You can send out a byte[], or simply write it to the response output stream by returning StreamingOutput.
#GET
public StreamingOutput getString() {
return new StreamingOutput(){
#Override
public void write(OutputStream out)
throws IOException, WebApplicationException {
// write to the `out` stream
}
};
}
For anything more than that, you will have to greatly elaborate on your requirement. The information you've provided, (especially the highlighted line) doesn't quite paint a clear enough problem as to what actual problem is you are facing.

Related

Send HTML file in Apache Camel RouteBuilder

I am having HTML file which I want to send as a response for the rest call inside Apache camel RouteBuilder. The code looks like below
public class RestEndpointRouteBuilder extends RouteBuilder {
#Override
public void configure() {
rest("/form")
.post()
.produces(MediaType.TEXT_HTML_VALUE)
.to("file:target/classes/static/form.html");
}
But, I am getting below error when I call the API
org.apache.camel.component.file.GenericFileOperationFailedException: Cannot write null body to file: target\classes\static\form.html\ID-*****-***-****
at org.apache.camel.component.file.FileOperations.storeFile(FileOperations.java:245)
at org.apache.camel.component.file.GenericFileProducer.writeFile(GenericFileProducer.java:277)
at org.apache.camel.component.file.GenericFileProducer.processExchange(GenericFileProducer.java:165)
at org.apache.camel.component.file.GenericFileProducer.process(GenericFileProducer.java:79)
at org.apache.camel.util.AsyncProcessorConverterHelper$ProcessorToAsyncProcessorBridge.process(AsyncProcessorConverterHelper.java:61)
at org.apache.camel.processor.SendProcessor.process(SendProcessor.java:145)
Basically, I want to return an HTML file, which is a ReactJS application, alongwith JS minified files. Could someone please help me with this?
There are several problems in your code:
The more appropriate HTTP method is rather GET instead of POST
The file component here is a to endpoint so it is used as a producer, in other words, it will save into the file instead of reading it as you expect.
The URI of the file component is incorrect, the URI format is file:directoryName[?options] which means that target/classes/static/form.html is supposed to be a directory, not a file.
What you try to achieve could be done as follow:
rest("/form")
// Fix #1: Use "get" instead of "post"
.get()
.produces(MediaType.TEXT_HTML)
.to("direct:fileContent");
from("direct:fileContent")
// Fix #2: Use "pollEnrich" to use the file component as a
// consumer to read the file
// Fix #3: Fix the URI to have the directory name on one side
// and the file name on the other side
.pollEnrich("file:target/classes/static?fileName=form.html");
NB: Even if what I described above will work, please note that a rest endpoint is not meant to be used for static content, you are supposed to use a reverse proxy instead.

Save pdf on disk using JasperReportsViewResolver with Spring 4.x

I'm using Spring Boot, Spring Data REST, Jasper Report (6.x).
I created a REST controller that should export a PDF report on disk and return a "ok" string to the client. So, it's a bit different from the usual use case in which the user what the PDF is sent back to the client.
According to best practice, I'm using the solution 4 of this reply: https://stackoverflow.com/a/27532493/2012635 for the "normal" use case in which the PDF is returned to the client:
#RequestMapping(value = "/refunds/{id}/export", method = RequestMethod.GET)
public ModelAndView exportPdf(#PathVariable("id") Long id, HttpServletRequest request, Locale locale) throws Exception {
Refund refund = refundRepository.findOne(id);
if (refund != null) {
ModelMap model = new ModelMap();
model.addAttribute("datasource", new JREmptyDataSource(1));
model.addAttribute("model", refund);
return new ModelAndView("RefundPdfView-IT", model);
} else {
throw new ResourceNotFoundException();
}
}
This approach is very clean, I've my mapping in the property file:
#REFUND
RefundPdfView-IT.(class)=org.springframework.web.servlet.view.jasperreports.JasperReportsPdfView
RefundPdfView-IT.url=classpath:/reports/accounting/refunds/Refund-IT.jrxml
I'm wondering if I can reuse this approach to save the PDF on the disk in the server rather than send it back to the client.
I would like to reuse the mapping defined without hardcoding the position and names of reports.
Some advice would be appreciated.
First thing I would like to point out is you will need JasperExportManager.
exportReportToPdfFile(JasperPrint jasperPrint, java.lang.String destFileName) 
to save a file locally in the server.
From your use case it is not clear why you want to save the file in server, I feel instead of saving the file you should save the search parameters. so that when you click on the parameters you will get/generate the pdf file again.
or alternatively you should use curl in the server and call the required url with parameters

What is the correct way to upload large Base64 encoded files with retrofit?

So I'm working with retrofit 2 which uses okhttp underneath. The below code snippet works but I get OOM errors for large files.
I believe this is because I am reading the file to a byte array.
What is the recommended way to work with this?
private void appendFileContentsToBody(Attachment attachment, MultipartBody.Builder requestBodyBuilder) throws IOException {
File file = new File(attachment.getAbsolutePath());
if(file.exists()){
RequestBody attachmentPart = RequestBody.create(null, Base64.getEncoder().encode(FileUtils.readFileToByteArray(file)));
requestBodyBuilder.addPart(Headers.of("X-Filename", attachment.getFilename()), attachmentPart);
}
}
You should not encode a file into Base64 before sending it, this should be done using stream, which will be done by Retrofit for you. So your code should look like
private void appendFileContentsToBody(Attachment attachment, MultipartBody.Builder requestBodyBuilder) throws IOException {
File file = new File(attachment.getAbsolutePath());
if(file.exists()){
RequestBody attachmentPart = RequestBody.create(MediaType.parse("application/pdf"), file);
requestBodyBuilder.addPart(Headers.of("X-Filename", attachment.getFilename()), attachmentPart);
}
}
where "application/pdf" - is MIME type of the particular file.
That way you will not suffer of OOM ever. However this approach might be implemented on a backend first cuz seems like now your backend implementation made applicable for web-apps only cuz it expects encoded file in a request body.

How to retrieve file from database for use by front-end code? (rest using java and jersey)

I'm working on a chat application, and I need to process a get request for a file that has been uploaded to the database. I'm not sure if I should return an output stream or a file or what.
The idea is that it will be something like any other chat application where the image appears as message are loaded. Using an output stream seemed like the best option, but I wasn't sure how to create the output stream from the information in the database, which includes an id, checksum, name, size, and mime type.
So my questions are:
How should I approach this?
if output stream is the best way, what's the ideal way to implement it?
Any guidance is appreciated, please let me know if I can make the question more clear, or if more details are necessary to answer the question.
What I couldn't understand how to do is this: serve the image to the front-end/client code. As it turns out, it was super easy.
#GET #javax.ws.rs.Path("/file/{fileId}")
public Response getFile(#Context SecurityContext sc, #PathParam("id") long topicId, #PathParam("fileId") long fileId) {
TopicFile tFile = topicAccessor.getFile(fileId);
String fileLocation = "/server/uploads/" + tFile.getChecksum();
File file = new File(fileLocation);
return Response.ok(file, tFile.getType()).build();
}
Here TopicFile holds metadata for the file in the database, and the files are named their checksum.
So basically the solution to my problem was to return a Response. I hadn't thought of this earlier because I "inherited" this code, and I trusted that the previous person had god reason not to use the Response class.

How To Download PDF file using Jersey?

I need to download pdf file using Jersey Web Services
i already do the following but the file size received is always 0 (zero).
#Produces({"application/pdf"})
#GET
#Path("/pdfsample")
public Response getPDF() {
File f = new File("D:/Reports/Output/Testing.pdf");
return Response.ok(f, "application/pdf").build();
}
Please help to do the correct way, thanks !!
Mkyong always delivers. Looks like the only thing you are missing is the correct response header.
http://www.mkyong.com/webservices/jax-rs/download-excel-file-from-jax-rs/
#GET
#Path("/get")
#Produces("application/pdf")
public Response getFile() {
File file = new File(FILE_PATH);
ResponseBuilder response = Response.ok((Object) file);
response.header("Content-Disposition","attachment; filename=test.pdf");
return response.build();
}
You can't just give a File as the entity, it doesn't work like that.
You need to read the file yourself and give the data (as a byte[]) as the entity.
Edit:
You might also want to look at streaming the output. This has two advantages; 1) it allows you to use serve files without the memory overhead of having to read the whole file and 2) it starts sending data to the client straight away without you having to read the whole file first. See https://stackoverflow.com/a/3503704/443515 for an example of streaming.
For future visitors,
This will find the blob located at the passed ID and return it as a PDF document in the browser(assuming it's a pdf stored in the database):
#Path("Download/{id}")
#GET
#Produces("application/pdf")
public Response getPDF(#PathParam("id") Long id) throws Exception {
Entity entity = em.find(ClientCase.class, id);
return Response
.ok()
.type("application/pdf")
.entity(entity.getDocument())
.build();
}

Categories

Resources