How is a PDF supposed to be encoded? - pdf

I'm trying to set up an API that generate PDF from web page (provided as URL). The API is gotenberg from thecodingmachine. I have it on Docker, it works just fine, I can't generate PDF through http request send with curl (for now I'm just trying to make it work, so I use the request provided as example in the documentation)
Now I am trying to make it work with my groovy/grails app. So I'm using the java tools to make the request.
Now here is my problem : the PDF file I get is blank (my app opend directly in my browser). It do has the right content, if I open it with the text editor, it's not empty, and it has almost the same content as the one I make using the curl request (which isn't blank).
I am 99% sure the problem come from the encoding. I tried changing the InputStreamReader encoding parameter, but it doesn't change anything. Here I put "X-MACROMAN" because that the encoding inside the pdf file that isn't blank, but it still doesn't change.
Here is my code :
static def execute(def apiURL)
{
def httpClient = HttpClients.createDefault()
// Request parameters and other properties.
def request = new HttpPost(apiURL)
MultipartEntityBuilder builder = MultipartEntityBuilder.create()
builder.addTextBody("remoteURL", 'https://google.com')
builder.addTextBody("marginTop", '0')
builder.addTextBody("marginBottom", '0')
builder.addTextBody("marginLeft", '0')
builder.addTextBody("marginRight", '0')
HttpEntity multipart = builder.build()
request.setEntity(multipart)
def response = httpClient.execute(request)
BufferedReader rd = new BufferedReader(
new InputStreamReader(response.getEntity().getContent(), "X-MACROMAN"))
StringBuffer result = new StringBuffer()
String line = ""
Boolean a = Boolean.FALSE
while ((line = rd.readLine()) != null) {
if(!a){
a = Boolean.TRUE
}
else {
result.append("\n")
}
result.append(line)
}
return result
I am 99% sure the problem come from the encoding. I tried changing the InputStreamReader encoding parameter, but it doesn't change anything. Here I put "X-MACROMAN" because that the encoding inside the pdf file that isn't blank, but it still doesn't change.
Did I made myself clear ? And does those who understands has any ideas why my PDFs are blank ?

Related

Return binary string as plain text in browser window (and not as a downloadable file)

I want to return the following protobuf serialised binary data to the browser (Chrome) and not as a downloadable file. I don't understand the mechanism that is prompting a download. It is not the mime type as I am using text/plain elsewhere.
Controller:
[HttpGet]
public async Task<ActionResult<string>> GenerateProtoFeed()
{
var feed = _gtfsrService.GenerateFeed();
using (var stream = new MemoryStream())
{
feed.WriteTo(stream);
stream.Position = 0;
using (var reader = new StreamReader(stream))
{
return Content(reader.ReadToEnd(), "text/plain");
}
}
}
What I really want is this (example) to be returned in the browser window:
2.0?????/?
-Mcycmmp9-o4C0qeoGdz*?
????/*0
rE6s0CN800STv61PAKtfHAL6wS0jjmZkSZwq1PAKtf8A08Z?
?
?#StationAlert Elevators at Commercial-Broadway and Brentwood Stations are temporarily out of service today. ^sdken
The browser handles responses from a server differently depending on how the user has configured it, and on the mime type of the response.
It looks like your browser's default behaviour for text/plain is to prompt a save action. If you set the mime type of your response to text/html, the browser should simply display it.
Note that this is of course technically incorrect in this case.

Prevent Caching .svg Images on Application Server

I have a JWS application that caches several different resource types. However, I do not want to cache .svg images. It seems that the framework does not honor the server side cache control HTTP headers that I have set.
I was wondering if there is some other way that I could load .svg images without caching. I am open to putting a solution in my loadSVGDocument() method, but my code is currently built around Apache Batik for loading .svg files. Is there a solution to pass an InputStream with a noCache flag within the Batik library similar to what DocumentBuilderFactory provides below?
URL url = new URL(fileLocation);
URLConnection connection = url.openConnection();
// Prevent JavaWebStart from returning cached copy.
connection.setUseCaches(false);
// Now fetch the content, e.g.
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
DocumentBuilder db = dbf.newDocumentBuilder();
Document doc = db.parse(connection.getInputStream());
Here is my current loadSVGDocument() method that uses several Apache Batik fields:
public void loadSVGDocument(final String url)
{
System.out.println("THE SVG URL: " + url);
String oldURI = null;
if (svgDocument != null)
{
oldURI = svgDocument.getURL();
}
final ParsedURL newURI = new ParsedURL(oldURI, url);
String theUrl = newURI.toString();
fragmentIdentifier = newURI.getRef();
loader = new DocumentLoader(userAgent);
nextDocumentLoader = new SVGDocumentLoader(theUrl, loader);
nextDocumentLoader.setPriority(Thread.NORM_PRIORITY);
Iterator it = svgDocumentLoaderListeners.iterator();
while (it.hasNext())
{
nextDocumentLoader
.addSVGDocumentLoaderListener((SVGDocumentLoaderListener) it.next());
}
documentLoader = nextDocumentLoader;
nextDocumentLoader = null;
documentLoader.run();
}
For anyone interested, I found that I can call Batik's
DocumentLoader.loadDocument(URL url, InputStream is)
with the setUseCaches flag as false. Not only does this load the image, but it also removes it from the cache accordingly. Though not the best solution in the sense that it would be nice for JWS to honor my HTTP headers, this work-around is good enough.

Google Drive REST API update content as HTML with Landscape Orientation google-drive-sdk

I've developed a service to update the content of a google document from salesforce. Using the google drive rest API. https://developers.google.com/drive/v2/reference/
These are the steps I follow:
Get the Id of a shared document. (I called this the template)
Clone (copy) the document on Drive.
Get the content of that document in HTML form and save it in a string variable.
Replace some words on that string variable.
Update the new content on the new copied document.
It works great! BUT My problem is that IF the template (step 1) have a orientation landscape, when I update the document with the new content (step 5) the orientation changes to Portrait.
These are the request I do for it:
To COPY the file:
POST https://www.googleapis.com/drive/v2/files/FILEID/copy
public String post(String url, String jsonStr) {
HttpRequest req = createRequest();
req.setEndpoint(url);
req.setMethod('POST');
req.setHeader('Content-Type','application/json');
req.setBody(jsonStr);
HttpResponse res = sendRequest(req);
if (isOK(res)) {
return res.getBody();
}
throw buildResponseException(res);
}
To Get the HTML Content:
After copy the file it returns the parameters of the new created file, including "exportLinks". So I get the "text/html" export link. And do a GET to that URL.
To Update the Content:
PUT https://www.googleapis.com/upload/drive/v2/files/FILEID?uploadType=media
public String put(String url, Blob jsonStr) {
HttpRequest req = createRequest();
req.setEndpoint(url);
req.setMethod('PUT');
req.setHeader(HTTP_HEADER_CONTENT_TYPE, 'text/html');
req.setHeader(HTTP_HEADER_CONTENT_LENGTH, String.valueOf(jsonStr.size()));
req.setBodyAsBlob(jsonStr);
HttpResponse res = sendRequest(req);
if (isOK(res)) {
return res.getBody();
}
throw buildResponseException(res); }
I'm pretty sure the problem is after update the content but I haven't found why. Also, I used v3 of the API and is the same behavior.

Wicket 6 - Capturing HttpServletRequest parameters in Multipart form?

USing Wicket 6.17 and servlet 2.5, I have a form that allows file upload, and also has ReCaptcha (using Recaptcha4j). When the form has ReCaptcha without file upload, it works properly using the code:
final HttpServletRequest servletRequest = (HttpServletRequest ) ((WebRequest) getRequest()).getContainerRequest();
final String remoteAddress = servletRequest.getRemoteAddr();
final String challengeField = servletRequest.getParameter("recaptcha_challenge_field");
final String responseField = servletRequest.getParameter("recaptcha_response_field");
to get the challenge and response fields so that they can be validated.
This doesn't work when the form has the file upload because the form must be multipart for the upload to work, and so when I try to get the parameters in that fashion, it fails.
I have pursued trying to get the parameters differently using ServletFileUpload:
ServletFileUpload fileUpload = new ServletFileUpload(new DiskFileItemFactory(new FileCleaner()) );
String response = IOUtils.toString(servletRequest.getInputStream());
and
ServletFileUpload fileUpload = new ServletFileUpload(new DiskFileItemFactory(new FileCleaner()) );
List<FileItem> requests = fileUpload.parseRequest(servletRequest);
both of which always return empty.
Using Chrome's network console, I see the values that I'm looking for in the Request Payload, so I know that they are there somewhere.
Any advice on why the requests are coming back empty and how to find them would be greatly appreciated.
Update: I have also tried making the ReCaptcha component multipart and left out the file upload. The result is still the same that the response is empty, leaving me with the original conclusion about multipart form submission being the problem.
Thanks to the Wicket In Action book, I have found the solution:
MultipartServletWebRequest multiPartRequest = webRequest.newMultipartWebRequest(getMaxSize(), "ignored");
// multiPartRequest.parseFileParts(); // this is needed since Wicket 6.19.0+
IRequestParameters params = multiPartRequest.getRequestParameters();
allows me to read the values now using the getParameterValue() method.

How do I open a file when clicking an ActionLink?

How do I open an existing file on the server when a user clicks an actionlink? The following code works for downloading a file but I want to open a new browser window, or tab, and display the file contents.
public ActionResult Download()
{
return File(#"~\Files\output.txt", "application/text", "blahblahblah.txt");
}
You must add "inline" for a new tab.
byte[] fileBytes = System.IO.File.ReadAllBytes(contentDetailInfo.ContentFilePath);
Response.AppendHeader("Content-Disposition", "inline; filename=" + contentDetailInfo.ContentFileName);
return File(fileBytes, contentDetailInfo.ContentFileMimeType);
The way you're using the File() method is to specify a file name in the third argument, which results in a content-disposition header being sent to the client. This header is what tells a web browser that the response is a file to be saved (and suggests a name to save it). A browser can override this behavior, but that's not controllable from the server.
One thing you can try is to not specify a file name:
return File(#"~\Files\output.txt", "application/text");
The response is still a file, and ultimately it's still up to the browser what to do with it. (Again, not controllable from the server.) Technically there's no such thing as a "file" in HTTP, it's just headers and content in the response. By omitting a suggested file name, the framework in this case may omit the content-disposition header, which is your desired outcome. It's worth testing the result in your browser to see if the header is actually omitted.
Use a target of blank on your link to open it in a new window or tab:
Download File
However, forcing the browser to display the contents is out of your control, as it entirely depends on how the user has configured their browser to deal with files that are application/text.
If you are dealing with text, you can create a view and populate the text on that view, which is then returned to the user as a regular HTML page.
please try this and replace your controller name and action name in html action link
public ActionResult ShowFileInNewTab()
{
using (var client = new WebClient()) //this is to open new webclient with specifice file
{
var buffer = client.DownloadData("~\Files\output.txt");
return File(buffer, "application/text");
}
}
OR
public ActionResult ShowFileInNewTab()
{
var buffer = "~\Files\output.txt"; //bytes form this
return File(buffer, "application/text");
}
this is action link which show in new blank tab
<%=Html.ActionLink("Open File in New Tab", "ShowFileInNewTab","ControllerName", new { target = "_blank" })%>
I canĀ“t vote your answered as is useful, follow dow. Thanks very much !
public FileResult Downloads(string file)
{
string diretorio = Server.MapPath("~/Docs");
var ext = ".pdf";
file = file + extensao;
var arquivo = Path.Combine(diretorio, file);
var contentType = "application/pdf";
using (var client = new WebClient())
{
var buffer = client.DownloadData(arquivo);
return File(buffer, contentType);
}
}