Generating a PDF using a PUT operation - java

I have a web application that can display a generated PDF file to the user using the following Java code on the server:
#Path("MyDocument.pdf/")
#GET
#Produces({"application/pdf"})
public StreamingOutput getPDF() throws Exception {
return new StreamingOutput() {
public void write(OutputStream output) throws IOException, WebApplicationException {
try {
PdfGenerator generator = new PdfGenerator(getEntity());
generator.generatePDF(output);
} catch (Exception e) {
logger.error("Error getting PDF file.", e);
throw new WebApplicationException(e);
}
}
};
}
This code takes advantage of the fact that I only need so much data from the front end in order to generate the PDF, so it can easily be done using a GET function.
However, I now want to return a PDF in a more dynamic way, and need a bunch more information from the front end in order to generate the PDF. In other areas, I'm sending similar amounts of data and persisting it to the data store using a PUT and #FormParams, such as:
#PUT
#Consumes({"application/x-www-form-urlencoded"})
public void put(#FormParam("name") String name,
#FormParam("details") String details,
#FormParam("moreDetails") String moreDetails...
So, because of the amount of data I need to pass from the front end, I can't use a GET function with just query parameters.
I'm using Dojo on the front-end, and all of the dojo interactions really don't know what to do with a PDF returned from a PUT operation.
I'd like to not have to do this in two steps (persist the data sent in the put, and then request the PDF) simply because the PDF is more "transient" in this uses case, and I don't want the data taking up space in my data store.
Is there a way to do this, or am I thinking about things all wrong?
Thanks.

I can't quite understand what do you need to accomplish - looks like you want to submit some data to persist it and then return pdf as a result? This should be straightforward, doesn't need to be 2 steps, just submit, on the submit save the data and return PDF.
Is this your problem? Can you clarify?
P.S.
Ok, you need to do the following in your servlet:
response.setHeader("Content-disposition",
"attachment; filename=" +
"Example.pdf" );
response.setContentType( "application/pdf" );
Set the "content-length" on the response, otherwise the Acrobat Reader plugin may not work properly, ex. response.setContentLength(bos.size());
If you provide output in JSP you can do this:
<%# page contentType="application/pdf" %>

Related

Set Content-Type Azure Blob Storage

I am currently writing a backend which takes in one or many image/video-files to be uploaded into Azure Blob Storage. I am however struggling to set the Content-Type of the files. The Content-Type is by default set to be "application/octet-stream", but I want to dynamically set them by using the file.getContentType() method.
The code looks like this:
public void uploadToContainer(BlobClient blobClient, MultipartFile file) {
try {
blobClient.upload(file.getInputStream(), file.getSize());
} catch (Exception e) {
//TODO:
// Better error handling
e.printStackTrace();
}
}
Does anyone know how I can accomplish this?
Faced the same issue uploading JSON file, came up with this from stepping through the
blobClient.upload method you're current using:
BlobHttpHeaders jsonHeaders = new BlobHttpHeaders()
.setContentType(MediaType.APPLICATION_JSON_VALUE);
BinaryData data = BinaryData.fromStream(file.getInputStream(), file.getSize());
BlobParallelUploadOptions options = new BlobParallelUploadOptions(data)
.setRequestConditions(new BlobRequestConditions()).setHeaders(jsonHeaders);
blobClient.uploadWithResponse(options, null, Context.NONE);
Note this is using azure-storage-blob v12.19.0
To set content type of a blob at the time of uploading, you will need to use the following method: uploadWithResponse(InputStream data, long length, ParallelTransferOptions parallelTransferOptions, BlobHttpHeaders headers, Map<String,String> metadata, AccessTier tier, BlobRequestConditions requestConditions, Duration timeout, Context context) instead of upload method that you're using currently.
You will be able to define content type using BlobHttpHeaders.

Upload image to server using POST

I know that there are some similar questions to this one on the site, and I've read most of them. I've also Googled for a solution, but am still having issues.
So, in my project I need to catch multipart post requests that are used to send mixed data (an image, two strings (company, type), date data (month, year) and a few integers) from a client. Upon receiving this request I need to change contrast and brightness of the image, and modify the color to gray tones.
For debugging I use Postman Chrome Extension, and for now I am only focusing on sending the image. I've tested sending the request in different ways, in half of them I get a "404 Not Found" error, in the other half wrong data is returned (mostly array of 0). Below is the code used in my resource method:
#Component
#Path("/code")
#Produces("application/json")
public class EncodeResource extends BasicResource {
#POST
#Path("/encode")
#Consumes("multipart/form-data")
public String encodeImage(
#FormDataParam("image") InputStream imageInputStream) {
BufferedImage imageBuffer = null;
try {
imageBuffer = ImageIO.read(imageInputStream);
} catch (IOException e) {
e.printStackTrace();
}
if (imageBuffer != null)
return okResponse(<some parameters>);
else
return errorResponse(<some parameters>);
}
}
ImageInputStream contains some byte array, but ImageIO.read() always returns null. I tried different images with different extensions (which imageio can read by default, checked it), but got the same result. As I think, it happens cause of there are some "unnecessary" information in my inputStream, so imageio.read() can't convert it into any type of image. I've suddenly found it, when changed InputStream to File:
#FormDataParam("image") File imageInputStream
...and then checked saved by tomcat .tmp file. It looked like that:
------WebKitFormBoundary4nC1XD4cevbbRh7A
Content-Disposition: form-data; name="image"; filename="1.jpg">
Content-Type: image/jpeg
(a lot of bytes)
------WebKitFormBoundary4nC1XD4cevbbRh7A--
And of course imageio.read() returned null.
Summing up all of that, I have 2 questions actually:
Why did I get 404 error and how can i fix it? For example, I tried this and like here. And I had to delete the second #FormDataParam from here to receive at least something. Can it be cause of the Postman "specific" form-data requests?
Why did I get the wrong data? Maybe I can parse received file and get "correct" byte array? Or something else?..

Setting the mime type

I want to write an excel and send it to the user as a response in an application using Play framework 1.x. But I am not sure how to set the response content-type/MIME-type for returning doc or excel file.
Let me know the steps for this.
From the documentation:
To serve binary data, such as a file stored on the server, use the renderBinary method. For example, if you have a User model with a play.db.jpa.Blob photo property, add a controller method to load the model object and render the image with the stored MIME type:
public static void userPhoto(long id) {
final User user = User.findById(id);
response.setContentTypeIfNotSet(user.photo.type());
java.io.InputStream binaryData = user.photo.get();
renderBinary(binaryData);
}

How to get XML with line feeds using jquery?

I have a simple script, that fills html form with values recieved from server
$.ajax({
url: getUrl(),
dataType: "xml"
}).done(function(xml) {
//get values from xml file and fill in html form
});
and simple code on a server side, that generates xml
public void writeXmlValues() throws Exception {
final HttpServletResponse response = context.getHttpResponse();
response.setContentType("application/xml; charset=UTF-8");
PrintWriter out = response.getWriter();
try
{
writeXmlValues(out, values);
}
finally
{
try
{
out.close();
}
catch (Throwable ignored){}
}
}
I faced the problem when added textarea field in form. This field can contain text with line separators and I'm able to put multiline text in xml. The result will be as follows:
<?xml version='1.0' encoding='UTF-8'?>
<parameter name="Conclusion">eshgseht
awegewhw
agwhg</parameter>
But text in js callback looks little different (here is the code exactly as it IS):
<?xml version='1.0' encoding='UTF-8'?><parameter name="Conclusion">eshgseht awegewhw agwhg</parameter>
There is no line feeds anymore! This is not a fault of jquery (as far as I can see in Firebug, response already is an one-line text), this is not a fault of StAX (it generates proper xml). I have no idea what's going on.
Can I get line feeds with usage of XML format? Or I should use json or something else (this is not the preferred way)?
Update:
Finally I found the reason for this behavior. Response was interpreted as text/html even with setContentType("application/xml"). Thanks a lot for your suggestions.
Did you consider using CDATA to write the value? More info on CDATA and Example implementation

Editing response content on doView()

I have a simple JSR 286 Portlet that displays a user manual (pure HTML code, not JSP).
Actually, my doView method, just contains this :
public class UserManualPortlet extends GenericPortlet
{
#Override
protected void doView(RenderRequest request, RenderResponse response)
throws PortletException, IOException
{
PortletRequestDispatcher rd = getPortletContext().getRequestDispatcher(
"/html/usermanual.html");
rd.include(request, response);
}
}
This works as expected, however I'm having trouble when including images. I'm aware that the path to images should be something like :
<img src='<%=renderResponse.encodeURL(renderRequest.getContextPath() + "/html/image.jpg")%>'/>
However, my HTML file containing the user manual is used elsewhere, so I would like to preserve it as a pure HTML file.
Is there a way to dynamically replace my classic images urls by something like the example above ? Perhaps using the PrintWriter of the response ?
If such thing is not possible, I thing I would need to generate a JSP file during my Maven build.
Any solution or ideas are welcome.
With JSR-268 portlets you have a better way of referencing resources: create ResourceURL using renderResponse.createResourceURL() and then you set the resourceID in the ResourceURL. That should give more consistent results across all portlet containers.
That said, if you want to modify the generated content from your usermanual.html but you don't want to convert it to a JSP then, instead of using a request dispatcher, I would load the file contents on my own, parse it at the same time that I do the URL replacements and then print all the contents to the portlet's response.

Categories