2012-11-19 30 views
8

मैं एक जावा "फ़िल्टर" बनाने की कोशिश कर रहा हूं जो एक कस्टम HTTP अनुरोध शीर्षलेख का पता लगाता है, और प्रतिक्रिया शीर्षलेख डालने देता है ताकि फ़ाइल स्वचालित रूप से डाउनलोड हो जाए। प्रतिक्रिया शीर्षलेख जो इसके लिए सबसे महत्वपूर्ण है "सामग्री-प्रकार = अनुलग्नक" प्रतिक्रिया शीर्षलेख है।जावा फ़िल्टर प्रतिक्रिया शीर्षलेख सेट करने में विफल रहा

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

यह अनुरोध में एक्स-Wria-डाउनलोड हैडर से जोड़ दिया जाएगा: मैं एक HTTP अनुरोध वस्तु है कि कस्टम हैडर सम्मिलित करता है बनाया है। तो मैं एक जावा फ़िल्टर जो कि अनुरोध हेडर के लिए दिखता है और प्रतिक्रिया हेडर स्थापित करना चाहिए करने के लिए "सामग्री प्रकार = लगाव"

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 पर फ़िल्टर शामिल करने के लिए कोड है सभी जेएसपी फाइलें।

जो चीज मुझे परेशान कर रही है, वह यह है कि हेडर प्रतिक्रिया फ़ाइल पर सेट किया जा रहा है, लेकिन यह डाउनलोड नहीं हो रहा है। अगर मैं res.setHeader डालता हूं ("सामग्री-विस्थापन", "अनुलग्नक; फ़ाइल नाम = success सफलतापूर्वक पीडीएफ"); "if" कथन के बाहर लाइन, तो यह काम करेगी, लेकिन यह सभी जेएसपी के डाउनलोड व्यवहार को लागू करेगी जो मैं नहीं चाहता हूं।

यह सामग्री-स्वभाव क्यों लागू कर रहा है लेकिन जब मेरे पास res.setHeader है तो कथन में काम नहीं कर रहा है; और उसके बाद काम करते समय यह कथन के बाहर है? किसी भी विचार के लिए कि मैं वांछित व्यवहार कैसे प्राप्त कर सकता हूं (केवल jsp के लिए सामग्री स्वभाव लागू कर रहा हूं जिसे मैंने कस्टम अनुरोध शीर्षलेख लागू किया है)?

+0

आप यह सुनिश्चित करें कि कर रहे हैं एक्स जावा में Wria-डाउनलोड सही ढंग से प्राप्त किया गया है? क्या आप req.getHeader ("X-Wria-डाउनलोड") प्रिंट करने का प्रयास कर सकते हैं और देख सकते हैं कि जावा फ़िल्टर में वास्तव में यह सही ढंग से प्राप्त हुआ है या नहीं? –

+0

हां यह सही ढंग से प्राप्त कर रहा है। उपर्युक्त "अगर" कथन में: यदि (req.getHeader ("X-Wria-डाउनलोड")! = Null) {} यह कथन में प्रवेश करता है और यदि मैं System.out.println डालता हूं तो यह उस पंक्ति को प्रिंट करेगा। मैं फ़ाइल में सामग्री-विस्थापन भी लागू करता हूं, लेकिन सामग्री-प्रकार श्रृंखला में ओवरराइट हो जाता है। फ़िल्टर चरण। भले ही प्रतिक्रिया सामग्री-विस्थापन प्राप्त करती है, ऐसा लगता है कि ऐसा नहीं होता है (डाउनलोड नहीं करता है, बल्कि पेज के रूप में पीडीएफ खींचता है।) मुझे "एक्स-व्रिया-डाउनलोड" भी दिखाई देता है क्रोम डेवलपर टूल का उपयोग करते समय अनुरोध हेडर। –

+0

आश्चर्यजनक रूप से यदि: res.setHeader ("सामग्री-प्रकार", "एप्लिकेशन/पीडीएफ"); res.setHeader ("सामग्री-विस्थापन", "अनुलग्नक; filename = success.pff"); अगर कथन के बाहर रखा गया है, तो फ़िल्टर काम करेगा। यह मेरी समस्या का समाधान नहीं करता है, हालांकि मैं केवल उन फ़िल्टरों पर लागू फ़िल्टर चाहता हूं जिन्हें मैंने अपना कस्टम हेडर संलग्न किया है। –

उत्तर

0

इसे आज़माएं: अनुरोध हेडर मौजूद होने पर अनुरोध पर एक विशेषता सेट करें। फिर, chain.doFilter(...) के बाद विशेषता की जांच करें और फिर प्रतिक्रिया शीर्षलेख सेट करें।

+0

ठीक है तो मैंने ऐसा करने का प्रयास किया है। किसी कारण से, chain.doFilter के बाद, सामग्री-प्रकार हमेशा पाठ/html पर वापस आ जाता है। –

0

समस्या यह है कि आपके AjaxRequest (यहां XMLHttpRequest) का शीर्षलेख (एक्स-Wria-Download) फ़िल्टर है, फ़िल्टर से पहले आपके HttpServletRequest ऑब्जेक्ट में सेट नहीं किया जा रहा है।

मुझे लगता है कि बेहतर विचार आपके AJAX अनुरोध को संभालने के लिए एक समर्पित सर्वलेट का उपयोग करेगा।

+1

हेडर (एक्स-व्रिया-डाउनलोड) वास्तव में जावा फ़िल्टर पर जाने से पहले अनुरोध ऑब्जेक्ट पर लागू हो रहा प्रतीत होता है। डिबग मोड में फ़िल्टर के माध्यम से जाने पर यह कस्टम अनुरोध हेडर का पता लगाता है, और बाद में उपरोक्त कथन निष्पादित करता है: यदि (req.getHeader ("X-Wria-Download")! = Null) {}। –

11

मुझे लगता है कि आपकी समस्या आपके Web Context के निष्पादन के फ़िल्टर आदेश से संबंधित है, यानी कुछ फ़िल्टर, आपके वेब संदर्भ में, आपके फ़िल्टर के बाद निष्पादित होते हैं और शीर्षलेख को ओवरराइड करते हैं। chain.doFilter करने के लिए कॉल के बाद

  • हेडर सेट करें::

    सर्वलेट Filter तो तुम की कोशिश कर सकते Chain of Responsibility पैटर्न

    के एक कार्यान्वयन है

... 

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

इस तरह के बाद कि सर्वलेट कहा जाता है और, के रूप में नीचे की व्याख्या, यदि आपका फिल्टर पहले web.xml में घोषणा की, तो setHeader कोड पिछले निष्पादित हो जाएगा अपने कोड निष्पादित किया जाएगा में (देखें नीचे छवि)।

  • सुनिश्चित करें कि सर्वलेट निष्पादित होने के बाद आपका फ़िल्टर निष्पादित करने वाला अंतिम है, यानी।यह पहली बार सर्वलेट फ़िल्टर घोषित किया जाना चाहिए के रूप में समझाया here:

enter image description here

आप Filter1 (प्रथम web.xml में घोषित) देख सकते हैं पहले एक सर्वलेट से पहले मार डाला मार डाला जाता है और पिछले है सर्वलेट निष्पादित होने के बाद निष्पादित किया गया। इसलिए यदि आप हेडर सेटिंग को अंतिम फ़िल्टर करना सुनिश्चित करना चाहते हैं तो इसे फ़िल्टर 1 के रूप में घोषित करें।

निष्पादन के क्रम में घोषणा के आदेश से निर्धारित किया जाता है अपने तैनाती डिस्क्रिप्टर (web.xml):

सर्वलेट कल्पना (खंड 6.2.4):

"आदेश कंटेनर का उपयोग करता है फिल्टर की श्रृंखला बनाने में एक विशेष अनुरोध के लिए आवेदन किया गया है यूआरआई निम्नानुसार है:

"1। सबसे पहले, मेलिंग फ़िल्टर मैपिंग उसी क्रम में करें कि ये तत्व तैनाती वर्णनकर्ता में दिखाई देते हैं।

"2. अगला, मेलिंग फ़िल्टर मैपिंग उसी क्रम में है कि ये तत्व तैनाती वर्णनकर्ता में दिखाई देते हैं।"

तो यह सुनिश्चित करने के लिए कि इसे अपने web.xml में पहले फ़िल्टर के रूप में घोषित करें। इस तरह यह हेडर सेटिंग करने वाला आखिरी फ़िल्टर होगा। और, ज़ाहिर है, chain.doFilter पर कॉल करने के बाद, पहले से ही कहा गया है, अपने कोड में हेडर सेट करें।

+1

धन्यवाद! महत्वपूर्ण चीजें जिन्होंने मुझे इससे मदद की है वह यह है कि 1) सुनिश्चित करें कि आपका फ़िल्टर पहले जोड़ा गया है, इसलिए इसे अंतिम कहा जाएगा, और 2) सुनिश्चित करें कि आप * कॉलिंग श्रृंखला के बाद प्रतिक्रिया * संशोधित करें .doFilter (req, res), नहीं इससे पहले, या आपकी प्रतिक्रिया ओवरराइट हो सकती है। –

+0

दुर्भाग्य से यह ड्रॉपविज़ार्ड 0.6/जेट्टी 8. का उपयोग करके मेरे लिए काम नहीं करता है। (मैं कुकी मूल्यों को संशोधित करने की कोशिश कर रहा हूं।) किसी कारण से, चाहे मैं 'chain.doFilter()' कॉल जोड़ूं, मेरी प्रतिक्रिया वापस आती है शीर्षकों के मूल मूल्यों के साथ। मुझे अपनी समस्या को एक अलग, कम वांछनीय तरीके से हल करना पड़ा है, लेकिन अगर किसी और के पास कोई समस्या है तो मैं इस जवाब पर टिप्पणी कर रहा हूं। – DuffJ

+0

अच्छे विवरण के लिए धन्यवाद। मैंने जेटी 9.2 के साथ ऐसा फ़िल्टर करने की कोशिश की है लेकिन दुर्भाग्यवश यह भी काम नहीं करता है, ऐसा लगता है कि @DuffJ के समान ही समस्या थी। मेरे मामले में फ़िल्टर केवल तभी काम करता था जब मैंने इसे अपने 'web.xml' में अंतिम फ़िल्टर के रूप में घोषित किया। – Sky

2

मान लीजिए कि आप दूसरों द्वारा वर्णित प्रतिक्रिया रैपर का उपयोग करते हैं, तो संपूर्ण रहस्य है जब मूल प्रतिक्रिया पर getWriter() को कॉल करना है! ऐसा इसलिए है क्योंकि प्रतिक्रिया ऑब्जेक्ट लेखक के लिए पूछे जाने के बाद जोड़े गए सभी शीर्षलेखों को अनदेखा करता है!

तो, सुनिश्चित करें कि आप getWriter() को कॉल करने से पहले अपने सभी शीर्षलेख जोड़ दें। यहाँ doFilter() के लिए मेरे अनुक्रम की सिफारिश की है:

  1. एक प्रतिक्रिया आवरण

  2. chain.doFilter (origRequest, आवरण) बनाएं;

  3. असाइन मूल (!) प्रतिक्रिया के लिए सभी आवश्यक हेडर मूल प्रतिक्रिया

  4. कॉपी इस लेखक के आवरण की सामग्री से

  5. प्राप्त लेखक