I have a servlet deployed under http://ip:8080/simple
The servlet is under package a.b.c
I have an html page in a.b.resources
named Test.html
.
The html has an img
tag for an image.
In the servlet I do:
htmlFile = MyServlet.class.getResourceAsStream("/a/b/resources/Test.html");
resp.setContentType("text/html");
PrintWriter writer = resp.getWriter();
byte[] bytes=new byte[htmlFile.available()];
htmlFile.read(bytes);
resp.setContentLength(bytes.length);
writer.print(new String(bytes));
writer.flush();
writer.close();
The html page appears on the browser but in the place of the image I see its alt
description.
I have tried:
<img alt="Company A" src="./CompanyLogo.jpg">
<img alt="Company A" src="/a/b/resources/CompanyLogo.jpg">
<img alt="Company A" src="CompanyLogo.jpg">
But none of these works.
The jpg image is under /a/b/c/resources i.e. in the same directory as the HTML page.
I am using embedded Jetty.
What am I messing here?
It can either redirect to a page or directly write any content from the servlet itself. So, in short, yes, you can directly generate any content from servlet without creating any jsp or html. Just get the writer by calling response. getWriter() and write your HTML content to it.
Now let's explore this project. For creating a html file, right click on WebRoot -> New -> html -> write your html file name e.g. MyHtml. html -> Finish. As you can see that a html file is created named MyHtml.
Defines an object to assist a servlet in sending a response to the client. The servlet container creates a ServletResponse object and passes it as an argument to the servlet's service method. To send binary data in a MIME body response, use the ServletOutputStream returned by getOutputStream() .
The browser is trying to resolve those resources relative to the current request URI (as you see in browser address bar). Those resources of course does not exist in your public web content as you seem to have placed them in the classpath.
In order to solve this, you would really need to parse the HTML and change all domain-relative src
and/or href
attributes of <a>
, <img>
, <base>
, <link>
, <script>
, <iframe>
, etc elements to let them point to a servlet which streams those resources from the classpath to the HTTP response.
It's a bit of work, but Jsoup makes it easy. Here's an example which assumes that your servlet is mapped on an URL pattern of /proxy/*
.
String proxyURL = request.getContextPath() + "/proxy/";
InputStream input = MyServlet.class.getResourceAsStream("/a/b/resources" + request.getPathInfo());
if (request.getRequestURI().endsWith(".html")) { // A HTML page is been requested.
Document document = Jsoup.parse(input, "UTF-8", null);
for (Element element : document.select("[href]")) {
element.attr("href", proxyURL + element.attr("href"));
}
for (Element element : document.select("[src]")) {
element.attr("src", proxyURL + element.attr("src"));
}
response.setContentType("text/html;charset=UTF-8");
response.setCharacterEncoding("UTF-8");
response.getWriter().write(document.html());
}
else { // Other resources like images, etc which have been proxied to this servlet.
response.setContentType(getServletContext().getMimeType(request.getPathInfo()));
OutputStream output = response.getOutputStream();
byte[] buffer = new byte[8192];
for (int length = 0; (length = input.read(buffer)) > 0;) {
output.write(buffer, 0, length);
}
}
input.close();
Open it by http://yourdomain:yourport/contextname/proxy/test.html.
There is no way to do this without implementing a servlet that will read the image out of the resources file. Try this:
public void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException
{
byte[] bbuf = new byte[8192];
resp.setContentType(req.getSession().getServletContext().getMimeType( req.getPathInfo()));
InputStream in = MyImageServlet.class.getResourceAsStream("/"+req.getPathInfo());
OutputStream op = resp.getOutputStream();
int length;
while ((in != null) && ((length = in.read(bbuf)) != -1)){
op.write(bbuf,0,length);
op.flush();
}
in.close();
op.close();
}
then register it in your web.xml
like so
<servlet-mapping>
<servlet-name>fetchimage</servlet-name>
<url-pattern>/fetchimage/*</url-pattern>
</servlet-mapping>
and then use it like so
<img alt="Company A" src="/fetchimage/a/b/resources/CompanyLogo.jpg">
You WILL need to implement a lot of error checking (A LOT OF ERROR CHECKING, just to clarify :)), filter the paths to make sure that someone can't just read your class files using the same technique, but some variation on this should work for you.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With