在servlet响应中正确编写HTML页面

发布于 2024-12-04 01:59:44 字数 976 浏览 2 评论 0原文

我在 http://ip:8080/simple
下部署了一个 servlet 该servlet位于abc包下
我在 abresources 中有一个名为 Test.html 的 html 页面。

该 html 有一个用于图像的 img 标签。

在 servlet 中,我这样做:

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();

html 页面出现在浏览器上,但在图像的位置我看到了它的 alt 描述。
我已经尝试过:

<img alt="Company A" src="./CompanyLogo.jpg">

<img alt="Company A" src="/a/b/resources/CompanyLogo.jpg">

<img alt="Company A" src="CompanyLogo.jpg">

但这些都不起作用。
jpg 图像位于 /a/b/c/resources 下,即与 HTML 页面位于同一目录中。
我正在使用嵌入式 Jetty。

我在这里搞什么鬼?

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?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

梦纸 2024-12-11 01:59:44

浏览器正在尝试解析与当前请求 URI 相关的这些资源(如您在浏览器地址栏中看到的)。这些资源当然不存在于您的公共网络内容中,因为您似乎已将它们放置在类路径中。

为了解决这个问题,您确实需要解析 HTML 并更改 的所有与域相关的 src 和/或 href 属性>

这需要一些工作,但是 Jsoup 使这一切变得简单。下面的示例假设您的 servlet 映射到 /proxy/* 的 URL 模式上。

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();

通过 http://yourdomain:yourport/contextname/proxy/test.html 打开它。

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.

噩梦成真你也成魔 2024-12-11 01:59:44

如果不实现从资源文件中读取图像的 servlet,就无法做到这一点。试试这个:

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();  
}

然后像这样在您的 web.xml 中注册它

<servlet-mapping>
  <servlet-name>fetchimage</servlet-name>
  <url-pattern>/fetchimage/*</url-pattern>
</servlet-mapping>

,然后像这样使用它

<img alt="Company A" src="/fetchimage/a/b/resources/CompanyLogo.jpg">

您将需要实施大量的错误检查(大量的错误检查,只是为了澄清:)),过滤路径以确保有人不能使用相同的技术读取您的类文件,但对此的一些变体应该适合您。

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.

星軌x 2024-12-11 01:59:44

request.getRequestDispatcher("/a/b/Test.html").forward(请求,响应);

request.getRequestDispatcher("/a/b/Test.html").forward(request, response);

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文