2011-09-11 19 views
4

我下http://ip:8080/simple
該servlet部署一個servlet是包下a.b.c
我有a.b.resources一個HTML頁面命名Test.html寫在servlet響應的HTML頁面適當

該html有一個圖像的img標記。

在我做的servlet:

htmlFile = MyServlet.class.getResourceAsStream("https://stackoverflow.com/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="https://stackoverflow.com/a/b/resources/CompanyLogo.jpg"> 

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

但是,這些作品。
jpg圖像位於/ a/b/c /資源下,即位於與HTML頁面相同的目錄中。
我正在使用嵌入式Jetty。

我在這裏搞什麼?

+0

我認爲這是快速的方式 – Cratylus

回答

0

request.getRequestDispatcher(「/ a/b/Test.html」)。forward(request,response);

+1

這不起作用 – Cratylus

+0

http://download.oracle.com/docs/cd/E17802_01/products/products/servlet/2.3/javadoc/javax/servlet/RequestDispatcher.html#forward (javax.servlet.ServletRequest,javax.servlet.ServletResponse)。將來自servlet的請求轉發給其他資源(servlet,JSP文件或HTML文件)。如果你的HTML頁面打包在你的戰爭中的位置/a/b/Test.html,那麼它將起作用。 –

+0

可能是因爲碼頭 – Cratylus

1

如果沒有實現一個將從資源文件中讀取圖像的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"> 

,您將需要執行大量的錯誤檢查(A很多錯誤檢查,只是澄清:)),過濾路徑,以確保有人不能只使用相同的技術讀取您的類文件,但一些變化應該爲你工作。

+0

真的嗎?我認爲這是快速的方式。但瀏覽器得到一個html頁面。瀏覽器不使用'src'標籤來請求圖像嗎? – Cratylus

+0

是的,但標準的servlet文件處理程序不會反省所有查找文件的jar文件。如果您想快速*將所有圖像複製到項目的頂層目錄中。 – Femi

6

瀏覽器嘗試解析相對於當前請求URI的資源(如您在瀏覽器地址欄中看到的那樣)。這些資源當然不存在於您的公共Web內容中,因爲您似乎已將它們放入類路徑中。

爲了解決這個問題,你真的需要解析的HTML和更改所有域相對src和/或<a><img><base><link><script>,等元素href屬性,讓他們指向一個將這些資源從類路徑流式傳輸到HTTP響應的servlet。

這是一個工作,但Jsoup可以很容易。這裏有一個例子,假設你的servlet被映射到一個URL模式/proxy/*

String proxyURL = request.getContextPath() + "/proxy/"; 
InputStream input = MyServlet.class.getResourceAsStream("https://stackoverflow.com/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打開它。

+0

+ 1.感謝您的詳細回答。說實話,我覺得自己像一個白癡。我的意圖是在一個特定的實例發送一個帶有徽標圖像的禁止頁面。我認爲這是最快的方法(因爲我認爲在Jetty中它需要更多的罐子才能使用jsp)。看起來我錯了轉了 – Cratylus

+0

無論如何,我寧願把這些資源放在公開的網頁內容中。這一切都相當笨拙:) – BalusC

+0

在嵌入式碼頭中,不太確定公共Web內容放置在哪裏 – Cratylus