2012-11-19 7 views
8

사용자 정의 HTTP 요청 헤더를 감지하고 파일이 자동으로 다운로드되도록 응답 헤더를 삽입하는 Java "필터"를 만들려고합니다. 이에 가장 중요한 응답 헤더는 "Content-Type = Attachment"응답 헤더입니다.Java 필터가 응답 헤더를 설정하지 못했습니다.

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

이렇게하면 X-Wria-Download 헤더가 요청에 삽입됩니다. 그런 다음 그 요청 헤더를 찾는 자바 필터를 가지고 응답 헤더를 설정해야하는 "콘텐츠 유형 = 첨부 파일"

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


} 

그리고 물론 web.xml을가 필터를 포함하는 코드를 가지고 모든 JSP 파일.

나를 괴롭히는 것은 응답 파일에 헤더가 설정되어 있지만 다운로드가되지 않는다는 것입니다. res.setHeader ("Content-Disposition", "attachment; filename = success.pdf"); "if"문 외부의 줄이면 작동하지만, 원하지 않는 모든 JSP에 다운로드 동작을 적용합니다.

콘텐츠 처리를 적용하지만 if 문에 res.setHeader가있을 때 작동하지 않는 이유는 무엇입니까? 그런 다음 if 문 외부에있을 때 작업합니까? 원하는 동작을 얻을 수있는 방법에 대한 아이디어 (사용자 지정 요청 헤더를 적용한 jsp의 내용 처리에만 적용)?

+0

당신이 있는지 있습니까 X- Wria-Download가 Java로 올바르게 수신 되었습니까? req.getHeader ("X-Wria-Download")를 인쇄하고 실제로 자바 필터에서 올바르게 수신되는지 확인할 수 있습니까? –

+0

예 올바르게 수신 중입니다. 위의 "if"문에서 if (req.getHeader ("X-Wria-Download")! = null) {}은 문을 입력하고 System.out.println에 입력하면 해당 행을 출력합니다. 또한 Content-Disposition을 파일에 적용하지만 Content-Type은 체인에서 덮어 쓰여진 것처럼 보입니다. 필터 단계. 응답은 Content-Disposition을 얻었지만 마치 다운로드 한 것처럼 보이지 않고 pdf를 페이지로 가져옵니다. 또한 "X-Wria-Download"가 Chrome 개발자 도구를 사용할 때 요청 헤더 –

+0

이상하게도 : res.setHeader ("Content-Type", "application/pdf"); res.setHeader ("Content-Disposition", "attachment; filename = success.pdf"); 이 if 문 외부에 놓이면 필터가 작동합니다. 이것은 내가 내 사용자 정의 헤더를 첨부 한 서블릿에만 필터를 적용하기 때문에 내 문제는 해결되지 않습니다. –

답변

0

사용해보기 : 요청 헤더가있는 경우 요청에 속성을 설정하십시오. 그런 다음 chain.doFilter(...) 뒤에있는 특성을 확인하고 응답 헤더를 설정하십시오.

+0

그래, 내가이 일을 시도했다. 어떤 이유로, chain.doFilter 다음에 content-type은 항상 text/html로 되돌아갑니다. –

0

필터가 제공되기 전에 AjaxRequest (여기 XMLHttpRequest)의 헤더 (X-Wria-Download)가 HttpServletRequest 객체에 설정되어 있지 않습니다.

더 나은 생각은 전용 서블릿을 사용하여 Ajax 요청을 처리합니다..

+1

헤더 (X-Wria-Download)는 실제로 자바 필터에 전달되기 전에 요청 객체에 적용되는 것으로 보입니다. 디버그 모드의 필터를 통과 할 때 사용자 정의 요청 헤더를 감지하고 위에 if 문을 실행합니다. if (req.getHeader ("X-Wria-Download")! = null) {}. 감사합니다. –

11

귀하의 문제는 Web Context의 필터 실행 순서와 관련이 있습니다. 즉, 웹 컨텍스트의 일부 필터가 필터 다음에 실행되고 헤더를 무시합니다. chain.doFilter에 대한 호출 후

. 필터는 다음 setHeader 코드가 실행 된 마지막이 될 것입니다, web.xml 파일에 선언 된 첫 번째 경우, 아래에 설명 된 바와 같이 서블릿이 호출되고 그 후 코드가 실행됩니다 이런 식으로

... 

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

(참조 아래 이미지 참조).

  • 서블릿 실행 후 필터가 마지막으로 실행되는지 확인하십시오.here 설명으로는 첫 번째 서블릿 필터 선언해야합니다 :

enter image description here

당신이 필터 1 (web.xml 파일에 선언 된 첫 번째)에서 볼 수 있듯이이 실행되는 서블릿 전에 실행 첫 번째와 마지막 서블릿이 실행 된 후 실행되는 스크립트. 따라서 헤더를 설정하는 마지막 필터가되게하려면 Filter1로 선언하십시오.

실행 순서에 선언의 순서에 의해 결정되는 배치 기술자 (web.xml의)

서블릿 명세 (섹션 6.2.4)

"순서 용기 사용 특정 요청 URI에 대해 이 적용되는 필터 체인을 구축하는 경우 다음과 같습니다.

"1. 먼저 동일한 요소 인 의 일치하는 필터 매핑은 이러한 요소가 배포 설명자에 나타나도록 정렬합니다.

"2. 다음으로 동일한 의 일치하는 필터 매핑은 이러한 요소가 배포 설명자에 표시되도록합니다."

따라서 web.xml에서 첫 번째 필터로 선언하기 만하면됩니다. 이 방법으로 헤더를 설정하는 마지막 필터가됩니다. 그리고 이미 말한대로 chain.doFilter을 호출 한 후 코드에 헤더를 설정하십시오.

+1

! 첫 번째로 필터를 추가했는지 확인하여 마지막으로 호출되도록하고 2) chain.doFilter (req, res)를 호출 한 후 응답을 수정해야합니다. 전에, 또는 귀하의 응답을 덮어 쓸 수 있습니다. –

+0

불행히도 이것은 Dropwizard 0.6/Jetty 8을 사용하여 저에게 효과가 없었습니다. (쿠키 값을 수정하려고합니다.) 어떤 이유로'chain.doFilter()'호출을 추가해도 아무런 반응이 없습니다 헤더의 원래 값과 비교합니다. 나는 다른, 덜 바람직 한 방식으로 내 문제를 해결해야했지만, 나는 다른 사람들이 문제를 가지고있는 경우에 대비하여이 대답에 대해 논평하고있다. – DuffJ

+0

좋은 설명 주셔서 감사합니다. Jetty 9.2와 같은 필터를 사용하려고했지만 불행히도 @DuffJ와 동일한 문제가있는 것으로 보입니다. 제 경우에는 필터가'web.xml'에서 마지막 필터로 선언 된 경우에만 필터가 예상대로 작동했습니다. – Sky

2

여기에 설명 된대로 응답 래퍼를 사용한다고 가정하면 전체 응답은 원래 응답에서 getWriter()를 호출 할 때입니다! 그것은 응답 객체가 당신이 작가를 요청한 후에 추가 된 모든 헤더를 무시하기 때문입니다!

따라서 getWriter()를 호출하기 전에 모든 헤더를 추가해야합니다. 다음은 doFilter()에 대한 내 추천 순서입니다 :

  1. 가 응답 래퍼

  2. chain.doFilter (origRequest, 래퍼)를 작성; 원래 응답

  3. 복사이 라이터로 래퍼의 내용에서

  4. 지정 원본 (!) 응답에 필요한 모든 헤더

  5. 가져 오기 작가

관련 문제