Here is my code:
try
{
ByteArrayOutputStream os = new ByteArrayOutputStream();
ImageIO.write(image, "png", os);
byte[] bytes = os.toByteArray();
os.flush();
os.close();
String code = encode(bytes);
URL base = applet.getCodeBase();
URL url = new URL(base.getProtocol(),
base.getHost(),
base.getPort(),
"/image.php?code=" + code);
HttpURLConnection c = (HttpURLConnection) url.openConnection();
c.setRequestMethod("POST");
c.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
c.setDoOutput(true);
DataOutputStream s = new DataOutputStream(c.getOutputStream());
s.writeBytes("code=" + code);
applet.getAppletContext().showDocument(url, "_blank");
}
catch (Exception e)
{
e.printStackTrace();
JOptionPane.showMessageDialog(
this,
e.toString(),
"Error",
JOptionPane.ERROR_MESSAGE);
}
By the time I use showDocument, the POST request is already done, so what I'm really doing is showing a blank page (instead, I want to show the image). The source of image.php is this:
<?php
$code = base64_decode($_GET["code"]);
header('Content-Type: image/png');
echo $code;
?>
You are using POST on Java and GET on PHP...
Your showDocument and the applet's POST request are completely independent. The POST request is done by your applet, and the result would be only usable inside your applet (but you are not reading it at all - and I'm not sure it is even sent).
showDocument, in contrast, always does a GET request - there is no way to instruct the browser to use POST here. You might be able to fabricate a POST request for a new HTML page by using the JavaScript bridge from your applet, though.
Theoretically, it should work anyways, as you send the image data as part of the URL, too, but there might be a length limit for the URL data in the Web server, or in the link from Java-Plugin to the browser.
You could instead encode your image in a data: URL, and use this for showDocument.
URL url = new URL("data:image/png;base64," + code);
(I did not test if Java's URL class actually accepts this. Please try and report. I suppose it is subject to the same browser URL length limits.)
An alternative would be having the server store the image (at least for some short time). Then you would use your POST from the applet to upload the data, get back (short) some unique identifier, which you then would pass to the showDocument URL.
Related
spring boot or java read/open pdf url and ResponseEntity attachment file .pdf
Call the URL https://xxxxx.xxx/file.pdf
Read the file from step 1 and display it. By setting the response value as follows:
Content-Type : application/pdf
Content-Transfer-Encoding : binary
Content-disposition : attachment; filename=filename.pdf
Content-Length : xxxx
URL url = new URL(apiReportDomain
+ "/rest_v2/reports/reports/cms/loan_emergency/v1_0/RTP0003_02.pdf?i_ref_code=" + documentId);
System.out.println(url);
String encoding = Base64.getEncoder().encodeToString(
(apiReportUsername + ":" + apiReportPassword).getBytes(StandardCharsets.UTF_8));
HttpURLConnection connectionApi = (HttpURLConnection) url.openConnection();
connectionApi.setRequestMethod("GET");
connectionApi.setDoOutput(true);
connectionApi.setRequestProperty("Authorization", "Basic " + encoding);
connectionApi.setRequestProperty("Content-Type", "application/pdf");
InputStream content = connectionApi.getInputStream();
BufferedReader in = new BufferedReader(
new InputStreamReader(content));
StringBuilder sb = new StringBuilder();
int cp;
while ((cp = in.read()) != -1) {
sb.append((char) cp);
}
byte[] output = sb.toString().getBytes();
HttpHeaders responseHeaders = new HttpHeaders();
responseHeaders.set("charset", "utf-8");
responseHeaders.setContentType(MediaType.valueOf("application/pdf"));
responseHeaders.setContentLength(output.length);
responseHeaders.set("Content-disposition", "attachment; filename=filename.pdf");
return new ResponseEntity<byte[]>(output, responseHeaders, HttpStatus.OK);
enter image description here
which the result i got is a blank page But in fact, this PDF contains a full sheet of text.
Update this if it does or does not operate, I think the problem would be the https and certificate verification at client download by your original connection.
You need the certificate to decrypt the pdf and formally accept the certificate. See JCA cryptography API.
Also the following is best MIME type for sending binary download.
Content-Type : application/octet-stream
https://docs.oracle.com/javase/7/docs/api/javax/net/ssl/HttpsURLConnection.html
The issue is that the server needs to fetch the file from the internet, and then pass it on. Except of a redirect (which would look like cross-site traffic).
First write local code to fetch the PDF in a local test application.
It could be that you need to use java SE HttpClient.
It just might be you need to fake a browser as agent, and accept cookies, follow a redirect. That all can be tested by a browser's development page looking at the network traffic in detail.
Then test that you can store a file with the PDF response.
And finally wire the code in the spring application, which is very similar on yielding the response. You could start with a dummy response, just writing some hard-coded bytes.
After info in the question
You go wrong in two points:
PDFs are binary data, String is Unicode, with per char 2 bytes, requiring a conversion back and forth: the data will be corrupted and the memory usage twice, and it will be slow.
String.getBytes(Charset) and new String(byte[], Charset) prevent that the default Charset of the executing PC is used.
Keeping the PDF first entirely in memory is not needed. But then you are missing the Content-Length header.
InputStream content = connectionApi.getInputStream();
ByteArrayOutputStream baos = new ByteArrayOutputStream();
content.transferTo(baos);
byte[] output = baos.toByteArray();
HttpHeaders responseHeaders = new HttpHeaders();
responseHeaders.set("charset", "utf-8");
responseHeaders.setContentType(MediaType.valueOf("application/pdf"));
responseHeaders.setContentLength(output.length);
responseHeaders.set("Content-disposition",
"attachment; filename=filename.pdf");
I'm trying to use an existing API that calls for a json object to be "submitted" using POST, but the page also requires a few parameters in request, for this example we will use name, and email. I'm super new to REST so I'm probably making an ignorant mistake somewhere here.
Here is the code I have so far in my servlet:
String path = "http://www.test.com/submit";
URL url = new URL(path);
conn = (HttpURLConnection)url.openConnection();
conn.setDoOutput(true);
conn.setRequestMethod("POST");
conn.setRequestProperty("Content-Type", "application/json");
Gson gson = new Gson();
//julySchedule is the object I want to submit with this request alongside the parameters.
String input = gson.toJson(julySchedule);
OutputStream os = conn.getOutputStream();
os.write(input.getBytes());
os.flush();
if (conn.getResponseCode() != 200) {
throw new RuntimeException("HTTP POST Request Failed with Error code : "
+ conn.getResponseCode());
}
I've tried to put the parameters in the URL, like:
/submit?name=Name&email=test#gmail.com
But that didn't work, because POST requests wont accept parameters like that.
Then I tried to add it to the Output stream like:
String params = "name=Name&email=test#gmail.com"
OutputStream os = conn.getOutputStream();
os.write(path.toBytes());
os.write(input.getBytes());
os.flush();
But that didn't work either. Am I making a really dumb mistake somewhere?
It is perfectly fine for a POST request to contain query string(Though not best practice).
Since you use application/json as Content-Type, I assume your payload has to be a JSON object. You cannot mix your params in POST body. You have 2 options:
Kep email&name in QueryString, and json in POST payload: What you did should work.
Use POST payload only: Set Content-Type: application/x-www-form-urlencoded as follows: name=NAME&email=EMAIL&jsonPayLoad={Your Json Object}. Server should extract jsonPayLoad from POST payload.
Make sure to escape using encodeURIComponent before writing to POST output stream.
I'm using a function called UploadFFGS and this is its content:
URL url = new URL("http://linkedme.com/filebet.txt");
URLConnection ucn = url.openConnection();
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection = (HttpURLConnection) url.openConnection();
FileInputStream is = new FileInputStream("filebet.txt"); //before I download the same file because I must edit it and upload the new version
OutputStream ostream = connection.getOutputStream();
PrintWriter pwriter = new PrintWriter(ostream);
pwriter.print(jTextArea1.getText());
pwriter.close();
This program never uploads the file filebet I have on my desktop to my link (http://linkedme.com/filebet.txt). Any ideas? I call it in this way:
try {
UploadFFGS();
}
catch (MalformedURLException ex) {
Logger.getLogger(xGrep.class.getName()).log(Level.SEVERE, null, ex);
} catch (IOException ex) {
Logger.getLogger(xGrep.class.getName()).log(Level.SEVERE, null, ex);
}
Also, NetBeans gives me this error: "java.net.ProtocolException: cannot write to a URLConnection if doOutput=false - call setDoOutput(true)".
Your approach won't work because your API endpoint (most likely) is a regular file rather than an interpreted script. The endpoint must provide a API by means of which you upload a file (POST/PUT etc).
I have a different solution. Maybe this will be useful for someone.
Just have a look at your advanced proxy settings in your web browser.
System engineers in our company had changed the proxy settings but I was not aware of it.
This error cost me 3 work-days. I got this doOutput error while writing a ftp upload project in my company. I tried everything like adding conn.setDoOutput(true) or 'fifty shades' of similar solutions but non of them saved me.
But, after I changed my proxy settings to correct ones, the error dissapeared and now I am able to upload my files through ftp using urlConnection in java.
I used the code in the link below to make an upload process, and did not add anything except host, port, user and password.
http://www.ajaxapp.com/2009/02/21/a-simple-java-ftp-connection-file-download-and-upload/
I'm making a simple URL request with code like this:
URL url = new URL(webpage);
URLConnection urlConnection = url.openConnection();
InputStream is = urlConnection.getInputStream();
But on that last line, I'm getting the "redirected too many times error". If my "webpage" var is, say, google.com then it works fine, but when I try to use my servlet's URL then it fails. It seems I can adjust the number of times it follows the redirects (default is 20) with this:
System.setProperty("http.maxRedirects", "100");
But when I crank it up to, say, 100 it definitely takes longer to throw the error so I know it is trying. However, the URL to my servlet works fine in (any) browser and using the "persist" option in firebug it seems to only be redirecting once.
A bit more info on my servlet ... it is running in tomcat and fronted by apache using 'mod-proxy-ajp'. Also of note, it is using form authentication so any URL you enter should redirect you to the login page. As I said, this works correctly in all browsers, but for some reason the redirect isn't working with the URLConnection in Java 6.
Thanks for reading ... ideas?
It's apparently redirecting in an infinite loop because you don't maintain the user session. The session is usually backed by a cookie. You need to create a CookieManager before you use URLConnection.
// First set the default cookie manager.
CookieHandler.setDefault(new CookieManager(null, CookiePolicy.ACCEPT_ALL));
// All the following subsequent URLConnections will use the same cookie manager.
URLConnection connection = new URL(url).openConnection();
// ...
connection = new URL(url).openConnection();
// ...
connection = new URL(url).openConnection();
// ...
See also:
Using java.net.URLConnection to fire and handle HTTP requests
Duse, I have add this lines:
java.net.CookieManager cm = new java.net.CookieManager();
java.net.CookieHandler.setDefault(cm);
See this example:
java.net.CookieManager cm = new java.net.CookieManager();
java.net.CookieHandler.setDefault(cm);
String buf="";
dk = new DAKABrowser(input.getText());
try {
URL url = new URL(dk.toURL(input.getText()));
DataInputStream dis = new DataInputStream(url.openStream());
String inputLine;
while ((inputLine = dis.readLine()) != null) {
buf+=inputLine;
output.append(inputLine+"\n");
}
dis.close();
}
catch (MalformedURLException me) {
System.out.println("MalformedURLException: " + me);
}
catch (IOException ioe) {
System.out.println("IOException: " + ioe);
}
titulo.setText(dk.getTitle(buf));
I was using Jenkins on Tomcat6 on a unix environment and got this bug. For some reason, upgrading to Java7 solved it. I'd be interested to know exactly why that fixed it.
I had faced the same problem and it took considerable amount of time to understand the problem.
So to summarize the problem was in mismatch of headers.
Consider below being my Resource
#GET
#Path("booksMasterData")
#Produces(Array(core.MediaType.APPLICATION_JSON))
def booksMasterData(#QueryParam("stockStatus") stockStatus : String): Response = {
// some logic here to get the books and send it back
}
And here is client code, which was trying to connect to my above resource
ClientResponse clientResponse = restClient.resource("http://localhost:8080/booksService").path("rest").path("catalogue").path("booksMasterData").accept("application/boks-master-data+json").get(ClientResponse.class);
And the error was coming on exactly above line.
What was the problem?
My Resource was using
"application/json"
in
#Produces annotation
and my client was using
accept("application/boks-master-data+json")
and this was the problem.
It took me long to find out this as the error was no where related. Break through was when I tried to access my resource in postman with
Accept-> "application/json" header
it worked fine, however with
Accept-> "application/boks-master-data+json" header
it doesnt.
And again, even Postman was not giving me proper error. The error was too generic. Please see the below image for reference.
We have a .net forms auth enabled site that the user visits via a WebViewClient in our android app. One of the features of the site is the ability to login and download some PDF files, however you need to be logged in to download the PDFs.
We are currently implementing shouldOverrideUrlLoading and are downloading the pdf via the following code when the correct condition is met.
URL u = new URL(url);
URLConnection conn = u.openConnection();
int contentLength = conn.getContentLength();
DataInputStream stream = new DataInputStream(u.openStream());
byte[] buffer = new byte[contentLength];
stream.readFully(buffer);
stream.close();
DataOutputStream fos = new DataOutputStream(new FileOutputStream("/sdcard/download/file.pdf"));
fos.write(buffer);
fos.flush();
fos.close();
From the IIS logs, its apparent that IIS does not consider this request to be logged in and redirects it to the login page.
What we need is a way to download the file with the auth cookie persisted in the file download request but we are at a loss as to how to persist the cookie.
Another viable solution for us is to persist the auth cookie between the WebViewClient and the android browser. If we could do that, we'd just open the PDF file via the default action in the browser.
Edit: It looks like I can set the auth cookie manually via
conn.setRequestProperty("Cookie", "");
Now I just need to figure out how to read the auth cookie out of the WebViewClient
Since you're using ASP.NET Forms authentication, you'll need to copy the forms auth cookie from the WebView to the URLConnection. Luckily this is pretty straight forward. This code lives in an implementation of shouldOverrideUrlLoading
string url = "http://site/generatePdfBehindFormsAuth";
// get an instance of a cookie manager since it has access to our auth cookie
CookieManager cookieManager = CookieManager.getInstance();
// get the cookie string for the site. This looks something like ".ASPXAUTH=data"
String auth = cookieManager.getCookie(url).toString();
URLConnection conn = (URLConnection)new URL(url).openConnection();
// Set the cookie string to be sent for download. In our case we're just copying the
// entire cookie string from the previous connection, so all values stored in
// cookies are persisted to this new connection. This includes the aspx auth
// cookie, otherwise it would not be authenticated
// when downloading the file.
conn.setRequestProperty("Cookie", auth);
conn.setDoOutput(true);
conn.connect();
// get the filename from the servers response, its typical value is something like:
// attachment; filename="GeneratedPDFFilename.pdf"
String filename = conn.getHeaderField("Content-Disposition").split("\"")[1];
// by default, we'll store the pdf in the external storage directory
String fileRoot = "/sdcard/";
// Complete the download
FileOutputStream f = new FileOutputStream(new File(fileRoot, filename));
InputStream in = conn.getInputStream();
byte[] buffer = new byte[1024];
int len1 = 0;
while ( (len1 = in.read(buffer)) > 0 )
{
f.write(buffer,0, len1);
}
f.close();
in.close();
NOTE: One thing to be aware of is that you should NOT make a call to getContentLength on your URLConnection. After 4 hours of debugging, wireshark finally showed that, if you call getContentLength, the cookie would be sent for the request that gets the content length, but the cookie will not be sent for subsequent requests, even on the same instance of URLConnection. Maybe I am naive and this is by design (the documentation does not indicate that it is by design), but I was unable to manually set the cookie for the subsequent file request by calling setRequestProperty after calling getContentLength. If I attempted to do that, I'd get a force close.
Have you looked at the CookieSyncManager class? I believe this is what is needed to persist cookies received from the server and re-use them.
http://developer.android.com/reference/android/webkit/CookieSyncManager.html