How do I get an InputStream from a URL?
for example, I want to take the file at the url wwww.somewebsite.com/a.txt and read it as an InputStream in Java, through a servlet.
I've tried
InputStream is = new FileInputStream("wwww.somewebsite.com/a.txt");
but what I got was an error:
java.io.FileNotFoundException
Use java.net.URL#openStream() with a proper URL (including the protocol!). E.g.
InputStream input = new URL("http://www.somewebsite.com/a.txt").openStream();
// ...
See also:
Using java.net.URLConnection to fire and handle HTTP requests
Try:
final InputStream is = new URL("http://wwww.somewebsite.com/a.txt").openStream();
(a) wwww.somewebsite.com/a.txt isn't a 'file URL'. It isn't a URL at all. If you put http:// on the front of it it would be an HTTP URL, which is clearly what you intend here.
(b) FileInputStream is for files, not URLs.
(c) The way to get an input stream from any URL is via URL.openStream(), or URL.getConnection().getInputStream(), which is equivalent but you might have other reasons to get the URLConnection and play with it first.
Your original code uses FileInputStream, which is for accessing file system hosted files.
The constructor you used will attempt to locate a file named a.txt in the www.somewebsite.com subfolder of the current working directory (the value of system property user.dir). The name you provide is resolved to a file using the File class.
URL objects are the generic way to solve this. You can use URLs to access local files but also network hosted resources. The URL class supports the file:// protocol besides http:// or https:// so you're good to go.
Pure Java:
urlToInputStream(url,httpHeaders);
With some success I use this method. It handles redirects and one can pass a variable number of HTTP headers asMap<String,String>. It also allows redirects from HTTP to HTTPS.
private InputStream urlToInputStream(URL url, Map<String, String> args) {
HttpURLConnection con = null;
InputStream inputStream = null;
try {
con = (HttpURLConnection) url.openConnection();
con.setConnectTimeout(15000);
con.setReadTimeout(15000);
if (args != null) {
for (Entry<String, String> e : args.entrySet()) {
con.setRequestProperty(e.getKey(), e.getValue());
}
}
con.connect();
int responseCode = con.getResponseCode();
/* By default the connection will follow redirects. The following
* block is only entered if the implementation of HttpURLConnection
* does not perform the redirect. The exact behavior depends to
* the actual implementation (e.g. sun.net).
* !!! Attention: This block allows the connection to
* switch protocols (e.g. HTTP to HTTPS), which is <b>not</b>
* default behavior. See: https://stackoverflow.com/questions/1884230
* for more info!!!
*/
if (responseCode < 400 && responseCode > 299) {
String redirectUrl = con.getHeaderField("Location");
try {
URL newUrl = new URL(redirectUrl);
return urlToInputStream(newUrl, args);
} catch (MalformedURLException e) {
URL newUrl = new URL(url.getProtocol() + "://" + url.getHost() + redirectUrl);
return urlToInputStream(newUrl, args);
}
}
/*!!!!!*/
inputStream = con.getInputStream();
return inputStream;
} catch (Exception e) {
throw new RuntimeException(e);
}
}
Full example call
private InputStream getInputStreamFromUrl(URL url, String user, String passwd) throws IOException {
String encoded = Base64.getEncoder().encodeToString((user + ":" + passwd).getBytes(StandardCharsets.UTF_8));
Map<String,String> httpHeaders=new Map<>();
httpHeaders.put("Accept", "application/json");
httpHeaders.put("User-Agent", "myApplication");
httpHeaders.put("Authorization", "Basic " + encoded);
return urlToInputStream(url,httpHeaders);
}
Here is a full example which reads the contents of the given web page.
The web page is read from an HTML form. We use standard InputStream classes, but it could be done more easily with JSoup library.
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>commons-validator</groupId>
<artifactId>commons-validator</artifactId>
<version>1.6</version>
</dependency>
These are the Maven dependencies. We use Apache Commons library to validate URL strings.
package com.zetcode.web;
import com.zetcode.service.WebPageReader;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
#WebServlet(name = "ReadWebPage", urlPatterns = {"/ReadWebPage"})
public class ReadWebpage extends HttpServlet {
#Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
response.setContentType("text/plain;charset=UTF-8");
String page = request.getParameter("webpage");
String content = new WebPageReader().setWebPageName(page).getWebPageContent();
ServletOutputStream os = response.getOutputStream();
os.write(content.getBytes(StandardCharsets.UTF_8));
}
}
The ReadWebPage servlet reads the contents of the given web page and sends it back to the client in plain text format. The task of reading the page is delegated to WebPageReader.
package com.zetcode.service;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.stream.Collectors;
import org.apache.commons.validator.routines.UrlValidator;
public class WebPageReader {
private String webpage;
private String content;
public WebPageReader setWebPageName(String name) {
webpage = name;
return this;
}
public String getWebPageContent() {
try {
boolean valid = validateUrl(webpage);
if (!valid) {
content = "Invalid URL; use http(s)://www.example.com format";
return content;
}
URL url = new URL(webpage);
try (InputStream is = url.openStream();
BufferedReader br = new BufferedReader(
new InputStreamReader(is, StandardCharsets.UTF_8))) {
content = br.lines().collect(
Collectors.joining(System.lineSeparator()));
}
} catch (IOException ex) {
content = String.format("Cannot read webpage %s", ex);
Logger.getLogger(WebPageReader.class.getName()).log(Level.SEVERE, null, ex);
}
return content;
}
private boolean validateUrl(String webpage) {
UrlValidator urlValidator = new UrlValidator();
return urlValidator.isValid(webpage);
}
}
WebPageReader validates the URL and reads the contents of the web page.
It returns a string containing the HTML code of the page.
<!DOCTYPE html>
<html>
<head>
<title>Home page</title>
<meta charset="UTF-8">
</head>
<body>
<form action="ReadWebPage">
<label for="page">Enter a web page name:</label>
<input type="text" id="page" name="webpage">
<button type="submit">Submit</button>
</form>
</body>
</html>
Finally, this is the home page containing the HTML form.
This is taken from my tutorial about this topic.
Related
tl;dr: How can I get Google Cloud Vision OCR to work on Cloud Shell editor's localhost?
I'm using Google Cloud Shell editor, which contains a web preview feature that serves "local" webservers at URLs like https://8080-dot-10727374-dot-devshell.appspot.com/index.html.
I'm following this tutorial for Cloud Vision OCR. I put that example code into a servlet that uses Blobstore as an image host:
package com.google.servlets;
import com.google.appengine.api.blobstore.BlobInfo;
import com.google.appengine.api.blobstore.BlobInfoFactory;
import com.google.appengine.api.blobstore.BlobKey;
import com.google.appengine.api.blobstore.BlobstoreService;
import com.google.appengine.api.blobstore.BlobstoreServiceFactory;
import com.google.appengine.api.images.ImagesService;
import com.google.appengine.api.images.ImagesServiceFactory;
import com.google.appengine.api.images.ServingUrlOptions;
import com.google.cloud.vision.v1.AnnotateImageRequest;
import com.google.cloud.vision.v1.AnnotateImageResponse;
import com.google.cloud.vision.v1.BatchAnnotateImagesResponse;
import com.google.cloud.vision.v1.Feature;
import com.google.cloud.vision.v1.Image;
import com.google.cloud.vision.v1.ImageAnnotatorClient;
import com.google.cloud.vision.v1.ImageSource;
import com.google.cloud.vision.v1.TextAnnotation;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* When the user submits the form, Blobstore processes the file upload and then forwards the request
* to this servlet. This servlet can then analyze the image using the Vision API.
*/
#WebServlet("/image-analysis")
public class ImageAnalysisServlet extends HttpServlet {
#Override
public void doPost(HttpServletRequest request, HttpServletResponse response) throws IOException {
PrintWriter out = response.getWriter();
// Get the BlobKey that points to the image uploaded by the user.
BlobKey blobKey = getBlobKey(request, "image");
// Get the URL of the image that the user uploaded.
String imageUrl = getUploadedFileUrl(blobKey);
// Extract text from the image
String text = detectDocumentText(imageUrl);
// Output some HTML.
response.setContentType("text/html");
out.println("<p>Here's the image you uploaded:</p>");
out.println("<a href=\"" + imageUrl + "\">");
out.println("<img src=\"" + imageUrl + "\" />");
out.println("</a>");
out.println("<h1>text: " + text + "</h1>");
}
/**
* Returns the BlobKey that points to the file uploaded by the user, or null if the user didn't
* upload a file.
*/
private BlobKey getBlobKey(HttpServletRequest request, String formInputElementName) {
BlobstoreService blobstoreService = BlobstoreServiceFactory.getBlobstoreService();
Map<String, List<BlobKey>> blobs = blobstoreService.getUploads(request);
List<BlobKey> blobKeys = blobs.get("image");
// User submitted form without selecting a file, so we can't get a BlobKey. (dev server)
if (blobKeys == null || blobKeys.isEmpty()) {
return null;
}
// Our form only contains a single file input, so get the first index.
BlobKey blobKey = blobKeys.get(0);
// User submitted form without selecting a file, so the BlobKey is empty. (live server)
BlobInfo blobInfo = new BlobInfoFactory().loadBlobInfo(blobKey);
if (blobInfo.getSize() == 0) {
blobstoreService.delete(blobKey);
return null;
}
return blobKey;
}
/** Returns a URL that points to the uploaded file. */
private String getUploadedFileUrl(BlobKey blobKey) {
ImagesService imagesService = ImagesServiceFactory.getImagesService();
ServingUrlOptions options = ServingUrlOptions.Builder.withBlobKey(blobKey);
String url = imagesService.getServingUrl(options);
// GCS's localhost preview is not actually on localhost,
// so make the URL relative to the current domain.
if(url.startsWith("http://localhost:8080/")){
url = url.replace("http://localhost:8080/", "https://8080-dot-10727374-dot-devshell.appspot.com/");
}
return url;
}
private String detectDocumentText(String path) throws IOException {
List<AnnotateImageRequest> requests = new ArrayList<>();
ImageSource imgSource = ImageSource.newBuilder().setImageUri(path).build();
Image img = Image.newBuilder().setSource(imgSource).build();
Feature feat = Feature.newBuilder().setType(Feature.Type.DOCUMENT_TEXT_DETECTION).build();
AnnotateImageRequest request = AnnotateImageRequest.newBuilder().addFeatures(feat).setImage(img).build();
requests.add(request);
// Initialize client that will be used to send requests. This client only needs to be created
// once, and can be reused for multiple requests. After completing all of your requests, call
// the "close" method on the client to safely clean up any remaining background resources.
try (ImageAnnotatorClient client = ImageAnnotatorClient.create()) {
BatchAnnotateImagesResponse response = client.batchAnnotateImages(requests);
List<AnnotateImageResponse> responses = response.getResponsesList();
client.close();
// Check to see if any of the responses are errors
for (AnnotateImageResponse res : responses) {
if (res.hasError()) {
System.out.format("Error: %s%n", res.getError().getMessage());
return "Error: " + res.getError().getMessage();
}
// For full list of available annotations, see http://g.co/cloud/vision/docs
TextAnnotation annotation = res.getFullTextAnnotation();
return annotation.getText();
}
}
catch(Exception e) {
return "ERROR: ImageAnnotatorClient Failed, " + e;
}
// Case where the ImageAnnotatorClient works, but there are no responses from it.
return "Error: No responses";
}
}
When I deploy to a real server using the mvn package appengine:deploy command, this works perfectly:
(Well, as perfectly as can be expected from this test image.)
However, if I deploy to a "local" devserver using the mvn package appengine:run command, then Google Cloud Vision returns a generic "Bad image data" error:
I'm guessing this is because the image URL (https://8080-dot-10727374-dot-devshell.appspot.com/_cloudshellProxy/_ah/img/TjxgeYiHlCkix-XRj94jnw) is not publicly accessible, because it's running on a "fake" localhost that requires me to be logged into my Google account to see.
How can I get Google Cloud Vision OCR to work on Cloud Shell editor's "fake" localhost?
Cloud Vision also supports reading image bytes directly rather than going through a URL. Switching to that allowed me to bypass the requirement to have a publicly accessible URL.
The line that matters is this one:
Image img = Image.newBuilder().setContent(ByteString.copyFrom(bytes)).build();
...where bytes come from what's stored in Blobstore.
Full code for reference:
package com.google.servlets;
import com.google.appengine.api.blobstore.BlobInfo;
import com.google.appengine.api.blobstore.BlobInfoFactory;
import com.google.appengine.api.blobstore.BlobKey;
import com.google.appengine.api.blobstore.BlobstoreService;
import com.google.appengine.api.blobstore.BlobstoreServiceFactory;
import com.google.appengine.api.images.ImagesService;
import com.google.appengine.api.images.ImagesServiceFactory;
import com.google.appengine.api.images.ServingUrlOptions;
import com.google.cloud.vision.v1.AnnotateImageRequest;
import com.google.cloud.vision.v1.AnnotateImageResponse;
import com.google.cloud.vision.v1.BatchAnnotateImagesResponse;
import com.google.cloud.vision.v1.Feature;
import com.google.cloud.vision.v1.Image;
import com.google.cloud.vision.v1.ImageAnnotatorClient;
import com.google.cloud.vision.v1.ImageSource;
import com.google.cloud.vision.v1.TextAnnotation;
import com.google.protobuf.ByteString;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* When the user submits the form, Blobstore processes the file upload and then forwards the request
* to this servlet. This servlet can then analyze the image using the Vision API.
*/
#WebServlet("/image-analysis")
public class ImageAnalysisServlet extends HttpServlet {
#Override
public void doPost(HttpServletRequest request, HttpServletResponse response) throws IOException {
PrintWriter out = response.getWriter();
// Get the BlobKey that points to the image uploaded by the user.
BlobKey blobKey = getBlobKey(request, "image");
// Get the URL of the image that the user uploaded.
String imageUrl = getUploadedFileUrl(blobKey);
byte[] blobBytes = getBlobBytes(blobKey);
// Extract text from the image
String text = detectDocumentText(blobBytes);
// Output some HTML.
response.setContentType("text/html");
out.println("<p>Here's the image you uploaded:</p>");
out.println("<a href=\"" + imageUrl + "\">");
out.println("<img src=\"" + imageUrl + "\" />");
out.println("</a>");
out.println("<h1>text: " + text + "</h1>");
}
private byte[] getBlobBytes(BlobKey blobKey) throws IOException {
BlobstoreService blobstoreService = BlobstoreServiceFactory.getBlobstoreService();
ByteArrayOutputStream outputBytes = new ByteArrayOutputStream();
int fetchSize = BlobstoreService.MAX_BLOB_FETCH_SIZE;
long currentByteIndex = 0;
boolean continueReading = true;
while (continueReading) {
// end index is inclusive, so we have to subtract 1 to get fetchSize bytes
byte[] b =
blobstoreService.fetchData(blobKey, currentByteIndex, currentByteIndex + fetchSize - 1);
outputBytes.write(b);
// if we read fewer bytes than we requested, then we reached the end
if (b.length < fetchSize) {
continueReading = false;
}
currentByteIndex += fetchSize;
}
return outputBytes.toByteArray();
}
/**
* Returns the BlobKey that points to the file uploaded by the user, or null if the user didn't
* upload a file.
*/
private BlobKey getBlobKey(HttpServletRequest request, String formInputElementName) {
BlobstoreService blobstoreService = BlobstoreServiceFactory.getBlobstoreService();
Map<String, List<BlobKey>> blobs = blobstoreService.getUploads(request);
List<BlobKey> blobKeys = blobs.get("image");
// User submitted form without selecting a file, so we can't get a BlobKey. (dev server)
if (blobKeys == null || blobKeys.isEmpty()) {
return null;
}
// Our form only contains a single file input, so get the first index.
BlobKey blobKey = blobKeys.get(0);
// User submitted form without selecting a file, so the BlobKey is empty. (live server)
BlobInfo blobInfo = new BlobInfoFactory().loadBlobInfo(blobKey);
if (blobInfo.getSize() == 0) {
blobstoreService.delete(blobKey);
return null;
}
return blobKey;
}
/** Returns a URL that points to the uploaded file. */
private String getUploadedFileUrl(BlobKey blobKey) {
ImagesService imagesService = ImagesServiceFactory.getImagesService();
ServingUrlOptions options = ServingUrlOptions.Builder.withBlobKey(blobKey);
String url = imagesService.getServingUrl(options);
// GCS's localhost preview is not actually on localhost,
// so make the URL relative to the current domain.
if(url.startsWith("http://localhost:8080/")){
url = url.replace("http://localhost:8080/", "https://8080-dot-10727374-dot-devshell.appspot.com/");
}
return url;
}
private String detectDocumentText(byte[] bytes) throws IOException {
List<AnnotateImageRequest> requests = new ArrayList<>();
Image img = Image.newBuilder().setContent(ByteString.copyFrom(bytes)).build();
Feature feat = Feature.newBuilder().setType(Feature.Type.DOCUMENT_TEXT_DETECTION).build();
AnnotateImageRequest request = AnnotateImageRequest.newBuilder().addFeatures(feat).setImage(img).build();
requests.add(request);
// Initialize client that will be used to send requests. This client only needs to be created
// once, and can be reused for multiple requests. After completing all of your requests, call
// the "close" method on the client to safely clean up any remaining background resources.
try (ImageAnnotatorClient client = ImageAnnotatorClient.create()) {
BatchAnnotateImagesResponse response = client.batchAnnotateImages(requests);
List<AnnotateImageResponse> responses = response.getResponsesList();
client.close();
// Check to see if any of the responses are errors
for (AnnotateImageResponse res : responses) {
if (res.hasError()) {
System.out.format("Error: %s%n", res.getError().getMessage());
return "Error: " + res.getError().getMessage();
}
// For full list of available annotations, see http://g.co/cloud/vision/docs
TextAnnotation annotation = res.getFullTextAnnotation();
return annotation.getText();
}
}
catch(Exception e) {
return "ERROR: ImageAnnotatorClient Failed, " + e;
}
// Case where the ImageAnnotatorClient works, but there are no responses from it.
return "Error: No responses";
}
}
I have seen this question so many places, But still not able to solve my requirement.
I have written code to generate excelsheet in Apache POI in ADF using Java and need to download it in browser as application will be in server side not always in my local machine.
Initially I tried code:
Desktop.getDesktop().open(new File(home + "/Downloads/" + "excel1" + filename + ".xls"));
It was downloading. But it is downloading only on my machine. It's not downloading on other machine.
Another solution:
file = new File(home + "/Downloads/" + "excel" + filename + ".xls");
Runtime.getRuntime().exec("cmd.exe /C start " + file);
But it is not working..
Another solution:
FacesContext fc = FacesContext.getCurrentInstance();
HttpServletResponse response = (HttpServletResponse) fc.getExternalContext().getResponse();
response.reset();
response.setContentType(“application/vnd.ms-excel”);
response.setHeader(“Content-Disposition”, “attachment; filename=\"excel.xlsx");
workbook.write(response.getOutputStream());
fc.responseComplete();
But this solution also does not work.
I have a suggestion to try to solve your problem.
I usually create a servlet that has the responsibility of downloading files in various formats: xls, pdf...
Here is an example of how this can be done:
import java.io.IOException;
import java.io.OutputStream;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class DownloadServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
#Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String fileName = request.getParameter("fileName");
String contentType = null;
if (fileName.endsWith("xls")) {
contentType = "application/octet-stream";
} else if (fileName.endsWith("pdf")) {
contentType = "application/pdf";
} else {
throw new RuntimeException("File type not found");
}
byte[] file = getFileOnServer(fileName);
response.setHeader("Content-disposition", "attachment;filename=" + fileName);
response.setHeader("charset", "iso-8859-1");
response.setContentType(contentType);
response.setContentLength(file.length);
response.setStatus(HttpServletResponse.SC_OK);
OutputStream outputStream = null;
try {
outputStream = response.getOutputStream();
outputStream.write(file, 0, file.length);
outputStream.flush();
outputStream.close();
response.flushBuffer();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
#Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doPost(request, response);
}
private byte[] getFileOnServer(String fileName) {
//implement your method to get the file in byte[]
return null;
}
}
So, you can call your servlet by URL:
http://localhost:8080/downloadServlet?fileName=myExcel.xls
or Form:
<form id="myDownloadServlet" action="downloadServlet" method="post">
<input type="text" id="fileName" name="fileName" />
<input type="submit" id="btnDownload" name="btnDownload" value="Download File" />
</form>
Don't forget to configure your web.xml or use the annotation #WebServlet.
I hope I've helped.
A more "professional" solution is to use Excel Api's for java, as Apache POI or JXL.
Here an example using JXL:
https://www.java-tips.org/other-api-tips-100035/93-jexcel/418-how-do-i-output-an-excel-file-from-a-servlet.html
And here one more using Apache POI:
https://programtalk.com/java/download-excel-using-servlet/
I hope this can helps you.
Best wishes!
I have a device which sends a JSON message via HTTP POST, to a web server. The server receives the JSON message as payload and decodes and prints it on the web page and also sends back a 200 OK response to the post.
Now, I am trying to replicate the same with a fake Java client code to act as the device and a fake server using servlet and JSP.
The servlet code and JSP run as one project and the Java code run as another project.
I am using Eclipse and Tomcat server.
My code is as follows:
Servlet Code:
(This is saved in Java Resources > src > DefaultPackage)
import java.io.*;
import javax.servlet.*;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.*;
import org.json.JSONException;
import org.json.JSONObject;
#WebServlet("/HelloWorld")
public class HelloWorld extends HttpServlet {
#Override
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
StringBuilder sb = new StringBuilder();
BufferedReader reader = request.getReader();
try {
String line;
while ((line = reader.readLine()) != null) {
sb.append(line).append('\n');
}
} finally {
reader.close();
}
System.out.println(sb.toString());
String api_key = null;
try {
//JSONObject jsonObj = new JSONObject(sb.toString().substring(sb.toString().indexOf('{')));
//JSONTokener t = new JSONTokener(sb.toString());
JSONObject obj = new JSONObject(sb.toString().replace("\uFEFF", ""));
System.out.println(obj.toString());
api_key= (String) obj.get("api_key");
//String node_number = (String) obj.get("node_number");
//String tag_statuses = (String) obj.get("tag_statuses");
//String voltage = (String) obj.get("voltage");
} catch (JSONException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("api_key:"+ api_key+"\n");
response.setStatus(response.SC_OK);
//response.setContentType("text/html");
//PrintWriter out = response.getWriter();
//out.println("<h1>"+out +"</h1>");
RequestDispatcher dispatcher = request.getRequestDispatcher("/WEB-INF/NewFile.jsp");
request.setAttribute("api_key", api_key); // set your String value in the attribute
dispatcher.forward( request, response );
}
public void doGet(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException {
doPost(req, res);
}
}
JSP Code:
(saved in WebContent)
<%# page language="java" contentType="text/html; charset=ISO-8859-1"
pageEncoding="ISO-8859-1"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Insert title here</title>
</head>
<body>
<table>
<tr>
<td><%=request.getAttribute("api_key")%></td>
</tr>
</table>
</body>
</html>
Java Application Code:
import java.io.*;
import java.net.*;
import org.json.JSONObject;
public class Client {
public static void main( String [] args ) {
try
{
JSONObject jsonObj = new JSONObject("{\"api_key\" : \"rien\", \"node_number\" : \"40\", \"tag_statuses\" : [[100,\"MISSING\"]], \"voltage\": \"345\", \"location\": [42.3432,23.0098]}");
URL url = new URL("http://localhost:95/sample/HelloWorld");
URLConnection uc = url.openConnection();
HttpURLConnection conn = (HttpURLConnection) uc;
conn.setDoInput(true);
conn.setDoOutput(true);
conn.setRequestMethod("POST");
conn.setRequestProperty("Content-type", "application/json");
PrintWriter pw = new PrintWriter(conn.getOutputStream());
//pw.write(jsonObj.toString());
pw.write(jsonObj.toString());
pw.close();
BufferedInputStream bis = new BufferedInputStream(conn.getInputStream());
bis.close();
int responseCode = conn.getResponseCode();
System.out.println("Response Code recieved is: " + responseCode);
}
catch (Exception e)
{
e.printStackTrace();
}
}
}
Here, I would like to see the content received by the servlet to be updated on the JSP, whenever some new content appears on the servlet, maybe by refreshing the webpage.
Now, When I try to run the code, without a jsp page I am receiving the content from the application and the java application is getting a 200 status update.
But when I try to include the JSP code, the JSP will run and I get a 'null' printed on JSP, but I get the data on console of servlet and I get the following exception on Java application code (instead of a 200 status message),
java.io.FileNotFoundException: http://localhost:95/sample/HelloWorld
at sun.net.www.protocol.http.HttpURLConnection.getInputStream0(Unknown Source)
at sun.net.www.protocol.http.HttpURLConnection.getInputStream(Unknown Source)
at Client.main(Client.java:21)
Could someone please help me in getting the content printed on the JSP real time and to avoid the error on the Java application? What am I doing wrong here?
Thanks.
First thing I recommend you to do is to debug things not with your own client but using curl, which is stable and already tested ad nauseam.
See the following: How to POST JSON data with Curl from Terminal/Commandline to Test Spring REST?
It looks like that your response is either 500 or 404 error code. I bet 500 since your server-side does not seem to be producing a 404.
Also, consider migrating both client and server to Jersey, which already solves all your problems.
https://jersey.java.net/
But if you want to stick to your implementation, it looks like the problem is on the way you are writing your client. The client thinks that you are trying to read a file (URL may also point to files, not only network URLs). Here again Jersey is your friend since, as I said before, it also has an HTTP client library.
From my personal experience with Java Servlets and JSPs the functionality of real time updating is not achievable through the method you are implementing. This is because when the request for the JSP is rendered, it will be rendered with whatever information your app contains when the request is received, then is sent to the browser. Once in the browser is all html/css, no java scriptlets, so it won't update automatically.
You can use web sockets to achieve this live-content feature or simply run a javascript function that calls the some servlet (ajax calls), retrieve the information, and change the html content.
Example of Ajax Call for email verification, used in the old days.
$.ajax(
{
url: "/validation", //URL of request
data:
{
param1: form.email.value //Parameter that will be sent.
},
async: false, // You can make it Async.
type: "POST", // Type of request.
dataType: "text", // Expected data type, might be json.
success: function(data) // If Ajax is success it will execute this function
{
if(data=="true")
{
missingStuff =" This email is already registered \n";
correoDiv.attr("class", "form-inline has-error");
}
else
{
correoDiv.attr("class", "form-inline has-success");
}
}
}
);
Another think you might want to check out it is : Socket.io,
they offer many features for realtime content.
I came across a helpful PDF generation code to show the file to the client in a Spring MVC application ("Return generated PDF using Spring MVC"):
#RequestMapping(value = "/form/pdf", produces = "application/pdf")
public ResponseEntity<byte[]> showPdf(DomainModel domain, ModelMap model) {
createPdf(domain, model);
Path path = Paths.get(PATH_FILE);
byte[] pdfContents = null;
try {
pdfContents = Files.readAllBytes(path);
} catch (IOException e) {
e.printStackTrace();
}
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.parseMediaType("application/pdf"));
String filename = NAME_PDF;
headers.setContentDispositionFormData(filename, filename);
headers.setCacheControl("must-revalidate, post-check=0, pre-check=0");
ResponseEntity<byte[]> response = new ResponseEntity<byte[]>(
pdfContents, headers, HttpStatus.OK);
return response;
}
I added a declaration that the method returns a PDF file ("Spring 3.0 Java REST return PDF document"): produces = "application/pdf".
My problem is that when the code above is executed, it immediately asks the client to save the PDF file. I want the PDF file to be viewed first in the browser so that the client can decide whether to save it or not.
I found "How to get PDF content (served from a Spring MVC controller method) to appear in a new window" that suggests to add target="_blank" in the Spring form tag. I tested it and as expected, it showed a new tab but the save prompt appeared again.
Another is "I can't open a .pdf in my browser by Java"'s method to add httpServletResponse.setHeader("Content-Disposition", "inline"); but I don't use HttpServletRequest to serve my PDF file.
How can I open the PDF file in a new tab given my code/situation?
Try
httpServletResponse.setHeader("Content-Disposition", "inline");
But using the responseEntity as follows.
HttpHeaders headers = new HttpHeaders();
headers.add("content-disposition", "attachment; filename=" + fileName)
ResponseEntity<byte[]> response = new ResponseEntity<byte[]>(
pdfContents, headers, HttpStatus.OK);
It should work
Not sure about this, but it seems you are using bad the setContentDispositionFormData, try>
headers.setContentDispositionFormData("attachment", fileName);
Let me know if that works
UPDATE
This behavior depends on the browser and the file you are trying to
serve. With inline, the browser will try to open the file within the
browser.
headers.setContentDispositionFormData("inline", fileName);
Or
headers.add("content-disposition", "inline;filename=" + fileName)
Read this to know difference between inline and attachment
SpringBoot 2
Use this code to display the pdf in the browser.
(PDF in directory resources -> CLASSPATH)
Using ResponseEntity<?>
#GetMapping(value = "/showPDF")
public ResponseEntity<?> exportarPDF( ){
InputStreamResource file = new InputStreamResource(service.exportPDF());
return ResponseEntity.ok()
.header(HttpHeaders.CONTENT_DISPOSITION, "inline;attachment; filename=ayuda.pdf")
.contentType(MediaType.APPLICATION_PDF)
.body(file);
}
#Service
public class AyudaServiceImpl implements AyudaService {
private static final Logger LOGGER = LoggerFactory.getLogger(LoadPDF.class);
LoadPDF pdf = new LoadPDF();
public InputStream exportPDF() {
LOGGER.info("Inicia metodo de negocio :: getPDF");
return pdf.getPDF();
}
}
---CLASE
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.ResourceUtils;
public class LoadPDF {
private static final Logger LOGGER = LoggerFactory.getLogger(LoadPDF.class);
public InputStream getPDF(){
try {
File file = ResourceUtils.getFile("classpath:ayuda.pdf");
LOGGER.debug("Ruta del archivo pdf: [" + file + "]");
InputStream in = new FileInputStream(file);
LOGGER.info("Encontro el archivo PDF");
return in;
} catch (IOException e) {
LOGGER.error("No encontro el archivo PDF",e.getMessage());
throw new AyudaException("No encontro el archivo PDF", e );
}
}
}
/* Here is a simple code that worked just fine to open pdf(byte stream) file
* in browser , Assuming you have a a method yourService.getPdfContent() that
* returns the bite stream for the pdf file
*/
#GET
#Path("/download/")
#Produces("application/pdf")
public byte[] getDownload() {
byte[] pdfContents = yourService.getPdfContent();
return pdfContents;
}
What happened is that since you "manually" provided headers to the response, Spring did not added the other headers (e.g. produces="application/pdf"). Here's the minimum code to display the pdf inline in the browser using Spring:
#GetMapping(value = "/form/pdf", produces = "application/pdf")
public ResponseEntity<byte[]> showPdf() {
// getPdfBytes() simply returns: byte[]
return ResponseEntity.ok(getPdfBytes());
}
I am new to servlet development, and I was reading an ebook, and found that I can redirect to a different web page using
setHeader("Location", "http://www.google.com")
But this is not working, as I have written this code as:
import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;
public class ModHelloWorld extends HttpServlet{
public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException{
// response.addHeader("Location", "http://www.google.com");
response.setHeader("Location", "http://www.google.com");
response.setContentType("text/html");
PrintWriter pw = response.getWriter();
pw.println("<html><head><title>Modified Hello World</title></head><body>");
pw.println("<h1>");
//getInitParameter function reads the contents ot init-param elements.
pw.println(getInitParameter("message"));
pw.println("</h1>");
pw.println("</body></html>");
pw.close();
}
}
i have checked the headers using my program to get the headers of the webpage which is as under:
import java.net.*;
import java.io.*;
class getHeaders{
public static void main(String args[]){
URL url = null;
URLConnection urc = null;
try {
url = new URL(args[0]);
urc = url.openConnection();
for(int i=0 ; ; i++) {
String name = urc.getHeaderFieldKey(i);
String value = urc.getHeaderField(i);
if(name == null && value == null)//both null so end of header
break;
else if(name == null){//first line of header{
System.out.println("Server HTTP version, Response code: ");
System.out.println(value);
System.out.println("ENd of first header field");
} else {
System.out.println("name of header is: " + name + " and its value is : " + value);
}
}
} catch(MalformedURLException e){
System.out.println("Malformed URL " + e.getMessage());
} catch(IOException e){
e.printStackTrace();
}
}
}
And i am getting the output as:
Server HTTP version, Response code:
HTTP/1.1 200 OK
ENd of first header field
name of header is: Server and its value is : Apache-Coyote/1.1
name of header is: Location and its value is : http://www.google.com
name of header is: Content-Type and its value is : text/html
name of header is: Content-Length and its value is : 101
name of header is: Date and its value is : Sat, 05 Mar 2011 15:27:29 GMT
But I was not redirected to google's page from my browser.
Thanks in advance:)
Oh no no! That's not how you redirect. It's far more simpler:
public class ModHelloWorld extends HttpServlet{
public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException{
response.sendRedirect("http://www.google.com");
}
}
Also, it's a bad practice to write HTML code within a servlet. You should consider putting all that markup into a JSP and invoking the JSP using:
response.sendRedirect("/path/to/mynewpage.jsp");
As you can see, the response is still HTTP/1.1 200 OK. To indicate a redirect, you need to send back a 302 status code:
response.setStatus(HttpServletResponse.SC_FOUND); // SC_FOUND = 302
Alternatively, you could try the following,
resp.setStatus(301);
resp.setHeader("Location", "index.jsp");
resp.setHeader("Connection", "close");
Another way of doing this if you want to redirect to any url source after the specified point of time
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
public class MyServlet extends HttpServlet
{
public void doGet(HttpServletRequest request,HttpServletResponse response) throws IOException
{
response.setContentType("text/html");
PrintWriter pw=response.getWriter();
pw.println("<b><centre>Redirecting to Google<br>");
response.setHeader("refresh,"5;https://www.google.com/"); // redirects to url after 5 seconds
pw.close();
}
}