2012-11-19 35 views
8

Tôi đang cố gắng tạo Bộ lọc "Java" để phát hiện Tiêu đề yêu cầu HTTP tùy chỉnh và chèn tiêu đề phản hồi để tệp sẽ tự động tải xuống. Tiêu đề phản hồi quan trọng nhất cho tiêu đề này là tiêu đề phản hồi "Content-Type = Attachment". Tôi đã tạo đối tượng yêu cầu HTTP chèn Tiêu đề tùy chỉnh:Bộ lọc Java không đặt tiêu đề phản hồi

function myHttpObject(filePath){ 
function makeHttpObject() { 
    return new XMLHttpRequest(); 
} 

var request = makeHttpObject(); 

request.open("GET", filePath, false); 
request.setRequestHeader("X-Wria-Download", "PDFdownload"); 
request.send(null); 
window.open(filePath); 
console.log(request.getAllResponseHeaders()); 
} 

Điều này sẽ chèn tiêu đề X-Wria-Tải xuống vào yêu cầu. Sau đó, tôi có một bộ lọc Java trông cho rằng tiêu đề yêu cầu và nên đặt tiêu đề đối phó với "Content-Type = đính kèm"

import javax.servlet.*; 
import javax.servlet.http.HttpServletRequest; 
import javax.servlet.http.HttpServletResponse; 
import javax.servlet.http.HttpSession; 
import java.io.IOException; 
import java.util.HashMap; 
import java.util.Map; 
public class Contenttypefilter implements Filter { 

protected FilterConfig filterConfig; 

public void init(FilterConfig filterConfig) throws ServletException { 
    this.filterConfig = filterConfig; 
} 

public void destroy() { 
    //noop 
} 

public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { 

    HttpServletRequest req = (HttpServletRequest) request; 
    HttpServletResponse res = (HttpServletResponse) response; 

    //get the headers we placed in the request 
    //based on those request headers, set some response headers 

    if(req.getHeader("X-Wria-Download") != null){ 
     res.setHeader("Content-Type", "application/pdf"); 
     res.setHeader("Content-Disposition", "attachment; filename=success.pdf"); 
    } 

    chain.doFilter(req,res); 
} 


} 

Và sau đó tất nhiên web.xml có mã để bao gồm các bộ lọc trên tất cả các tệp jsp.

Điều khiến tôi bối rối, là tiêu đề đang được đặt trên tệp phản hồi, nhưng nó không tải xuống như nó cần. Nếu tôi đặt res.setHeader ("Content-Disposition", "attachment; filename = success.pdf"); dòng bên ngoài câu lệnh "if", sau đó nó sẽ hoạt động, nhưng nó sẽ áp dụng hành vi tải xuống cho tất cả các JSP mà tôi không muốn.

Tại sao nó áp dụng bố cục nội dung nhưng không hoạt động khi tôi có res.setHeader trong câu lệnh if; và sau đó làm việc khi nó nằm ngoài câu lệnh if? Bất kỳ ý tưởng nào về cách tôi có thể có được hành vi mong muốn (chỉ áp dụng bố cục nội dung cho jsp là tôi đã áp dụng tiêu đề yêu cầu tùy chỉnh cho)?

+0

Bạn có chắc chắn rằng X- Wria-Download được nhận đúng trong Java? Bạn có thể thử in req.getHeader ("X-Wria-Download") và xem liệu nó có thực sự được nhận chính xác trong bộ lọc Java không? –

+0

Có nhận được chính xác. Trong câu lệnh "if" ở trên: if (req.getHeader ("X-Wria-Download")! = Null) {}, nó sẽ đi vào câu lệnh và nếu tôi đặt trong System.out.println nó sẽ in dòng đó ra. Tôi cũng áp dụng Content-Disposition cho tệp, nhưng Content-Type dường như bị ghi đè ở giai đoạn chain.Filter. Mặc dù phản hồi nhận được Nội dung-Bố trí, nó dường như không hành xử như thể nó đã làm (không tải xuống, nhưng thay vì kéo lên pdf như một trang.) Tôi cũng thấy "X-Wria-Download" trong tiêu đề yêu cầu khi sử dụng các công cụ dành cho nhà phát triển Chrome. –

+0

Kỳ lạ nếu: res.setHeader ("Content-Type", "application/pdf"); res.setHeader ("Nội dung-Bố trí", "tệp đính kèm; tên tệp = success.pdf"); được đặt bên ngoài câu lệnh if, sau đó bộ lọc sẽ hoạt động. Điều này không giải quyết vấn đề của tôi mặc dù kể từ khi tôi chỉ muốn các bộ lọc áp dụng cho servlets mà tôi đã đính kèm tiêu đề tùy chỉnh của tôi để. –

Trả lời

0

Hãy thử điều này: đặt thuộc tính theo yêu cầu nếu có tiêu đề yêu cầu. Sau đó, kiểm tra thuộc tính sau chain.doFilter(...) và đặt tiêu đề phản hồi sau đó.

+0

Ok vì vậy tôi đã thử làm điều này. Đối với một số lý do, sau chuỗi.doFilter, kiểu nội dung luôn chuyển về văn bản/html. –

0

Vấn đề là tiêu đề (X-Wria-Download) của AjaxRequest (ở đây XMLHttpRequest) không được đặt trong đối tượng HttpServletRequest của bạn trước khi bộ lọc đang được phục vụ.

Tôi nghĩ rằng tốt hơn Ý tưởng sẽ là sử dụng một Servlet chuyên dụng để xử lý yêu cầu ajax của bạn.

+1

Tiêu đề (X-Wria-Download) thực sự dường như được áp dụng cho đối tượng yêu cầu trước khi được chuyển tới Bộ lọc java. Khi đi qua bộ lọc trong chế độ gỡ lỗi, nó phát hiện tiêu đề yêu cầu tùy chỉnh, và sau đó thực thi câu lệnh if ở trên: if (req.getHeader ("X-Wria-Download")! = Null) {}. –

11

Tôi nghĩ vấn đề của bạn có liên quan đến thứ tự Bộ lọc thực thi Web Context của bạn, tức là một số bộ lọc, trong ngữ cảnh web của bạn, thực thi sau bộ lọc và ghi đè tiêu đề.

Các Servlet Filter là một thực hiện các Chain of Responsibility mẫu

Vì vậy, bạn có thể cố gắng:

  • Đặt tiêu đề sau khi cuộc gọi đến chain.doFilter:

.

... 

chain.doFilter(req,res); 

HttpServletRequest req = (HttpServletRequest) request; 
HttpServletResponse res = (HttpServletResponse) response; 

//get the headers we placed in the request 
//based on those request headers, set some response headers 

if(req.getHeader("X-Wria-Download") != null){ 
    res.setHeader("Content-Type", "application/pdf"); 
    res.setHeader("Content-Disposition", "attachment; filename=success.pdf"); 
} 

Bằng cách này mã của bạn sẽ được thực hiện sau đó Servlet được gọi và, như được giải thích dưới đây, nếu bộ lọc của bạn là người đầu tiên tuyên bố trong web.xml, sau đó mã setHeader sẽ là thực thi cuối cùng (xem hình ảnh dưới đây).

  • đảm bảo rằng bộ lọc của bạn là bộ lọc cuối cùng được thực hiện sau khi Servlet được thực thi, tức lànó phải được các servlet Lọc đầu tiên tuyên bố như được giải thích here:

enter image description here

Như bạn có thể nhìn thấy bộ lọc1 (người đầu tiên tuyên bố trong web.xml) là người đầu tiên thực hiện trước khi servlet được thực hiện và cuối cùng một thực hiện sau khi servlet được thực hiện. Vì vậy, nếu bạn muốn chắc chắn là Bộ lọc cuối cùng, hãy đặt tiêu đề, sau đó khai báo nó là Bộ lọc1.

Trình tự thực hiện được xác định bởi thứ tự kê khai trong Deployment Descriptor (web.xml):

Servlet spec (phần 6.2.4):

"Trình tự những ứng dụng chứa trong việc xây dựng chuỗi bộ lọc thành được áp dụng cho URI yêu cầu cụ thể như sau:

"1. Đầu tiên, ánh xạ bộ lọc phù hợp trong cùng một thứ tự mà các phần tử này xuất hiện trong bộ mô tả triển khai.

"2. Tiếp theo, ánh xạ bộ lọc phù hợp trong cùng một đơn đặt hàng xuất hiện trong bộ mô tả triển khai".

Vì vậy, hãy chắc chắn chỉ cần khai báo nó làm bộ lọc đầu tiên trong số web.xml của bạn. Bằng cách này, nó sẽ là bộ lọc cuối cùng thiết lập tiêu đề. Và, tất nhiên, đặt tiêu đề trong mã của bạn sau khi gọi chain.doFilter, như đã nói.

+1

cảm ơn! những điều quan trọng đã giúp tôi từ điều này là 1) Hãy chắc chắn rằng bộ lọc của bạn được thêm vào trước, vì vậy nó sẽ được gọi là cuối cùng và 2) đảm bảo bạn sửa đổi phản hồi * sau * call chain.doFilter (req, res), chứ không phải trước hoặc phản hồi của bạn có thể bị ghi đè. –

+0

Thật không may điều này đã không làm việc cho tôi bằng cách sử dụng Dropwizard 0.6/Jetty 8. (Tôi đang cố gắng sửa đổi các giá trị cookie.) Vì một lý do nào đó, không có vấn đề gì tôi thêm lệnh 'chain.doFilter()', phản hồi của tôi trở lại với các giá trị ban đầu của các tiêu đề. Tôi đã phải giải quyết vấn đề của mình theo một cách khác, ít hấp dẫn hơn, nhưng tôi chỉ bình luận về câu trả lời này trong trường hợp bất kỳ ai khác cũng có vấn đề. – DuffJ

+0

Cảm ơn bạn đã mô tả đúng. Tôi đã cố gắng để làm như một bộ lọc với Jetty 9.2 nhưng tiếc là nó cũng không làm việc, có vẻ là vấn đề tương tự như @ DuffJ đã có. Trong trường hợp của tôi, bộ lọc chỉ hoạt động như mong đợi nếu tôi khai báo nó là bộ lọc cuối cùng trong 'web.xml' của tôi. – Sky

2

Giả sử bạn sử dụng trình bao bọc phản hồi như được mô tả ở đây bởi những người khác, toàn bộ bí mật là khi gọi hàm getWriter() trên phản hồi ban đầu! Đó là bởi vì đối tượng phản hồi bỏ qua tất cả các tiêu đề được thêm vào SAU KHI bạn yêu cầu một nhà văn!

Vì vậy, hãy đảm bảo bạn thêm tất cả các tiêu đề của mình Trước khi bạn gọi hàm getWriter(). Đây là chuỗi khuyên của tôi cho doFilter():

  1. Tạo một wrapper phản ứng

  2. chain.doFilter (origRequest, wrapper);

  3. Gán tất cả các tiêu đề cần thiết với bản gốc (!) Đáp ứng

  4. Nhận nhà văn từ phản ứng ban đầu

  5. Sao chép nội dung của wrapper để nhà văn này

Các vấn đề liên quan