2009-03-12 12 views
7

मैं यह पता लगाने की कोशिश कर रहा हूं कि कोड का यह विशेष स्निपेट मेरे लिए क्यों काम नहीं कर रहा है। मुझे एक एपलेट मिला है जिसे एक पीडीएफ पढ़ना है और इसे पीडीएफ-रेंडरर लाइब्रेरी के साथ प्रदर्शित करना है, लेकिन किसी कारण से जब मैं अपने सर्वर पर बैठे .pdf फ़ाइलों में पढ़ता हूं, तो वे भ्रष्ट होने के रूप में समाप्त होते हैं। मैंने फ़ाइलों को फिर से लिखकर इसका परीक्षण किया है।जावा: यूआरएल से एक पीडीएफ फ़ाइल को एक एप्लेट में बाइट सरणी/बाइटबफर में पढ़ना

मैंने आईई और फ़ायरफ़ॉक्स दोनों में एप्लेट देखने की कोशिश की है और भ्रष्ट फाइलें होती हैं। मजेदार बात यह है कि, जब मैं सफारी (विंडोज़ के लिए) में एप्लेट देखने की कोशिश कर रहा हूं, तो फाइल वास्तव में ठीक है! मैं समझता हूं कि जेवीएम अलग हो सकता है, लेकिन मैं अभी भी खो गया हूं। मैंने जावा 1.5 में संकलित किया है। जेवीएम 1.6 हैं। स्निपेट जो फ़ाइल को पढ़ता है नीचे है।

public static ByteBuffer getAsByteArray(URL url) throws IOException { 
     ByteArrayOutputStream tmpOut = new ByteArrayOutputStream(); 

     URLConnection connection = url.openConnection(); 
     int contentLength = connection.getContentLength(); 
     InputStream in = url.openStream(); 
     byte[] buf = new byte[512]; 
     int len; 
     while (true) { 
      len = in.read(buf); 
      if (len == -1) { 
       break; 
      } 
      tmpOut.write(buf, 0, len); 
     } 
     tmpOut.close(); 
     ByteBuffer bb = ByteBuffer.wrap(tmpOut.toByteArray(), 0, 
             tmpOut.size()); 
     //Lines below used to test if file is corrupt 
     //FileOutputStream fos = new FileOutputStream("C:\\abc.pdf"); 
     //fos.write(tmpOut.toByteArray()); 
     return bb; 
} 

मुझे कुछ याद आना चाहिए, और मैं इसे समझने की कोशिश कर रहा हूं। कोई भी मदद बहुत ही सराहनीय होगी। धन्यवाद।


संपादित करें: आगे मेरी स्थिति, फ़ाइल इससे पहले कि मैं स्निपेट के साथ और बाद तो पढ़ में अंतर को स्पष्ट करने के लिए, कि लोगों को पढ़ने के बाद मैं उत्पादन काफी छोटे की तुलना में वे मूल रूप से कर रहे हैं कर रहे हैं। उन्हें खोलते समय, उन्हें .pdf फ़ाइलों के रूप में पहचाना नहीं जाता है। फेंकने वाले कोई अपवाद नहीं हैं जिन्हें मैं अनदेखा करता हूं, और मैंने कोई फायदा नहीं उठाया है।

यह स्निपेट सफारी में काम करता है, जिसका अर्थ है कि फाइलें पूरी तरह से पढ़ी जाती हैं, आकार में कोई फर्क नहीं पड़ता है, और किसी भी .pdf पाठक के साथ खोला जा सकता है। आईई और फ़ायरफ़ॉक्स में, फ़ाइलें हमेशा दूषित होने लगती हैं, लगातार एक ही छोटे आकार में।

मैंने प्रत्येक लूप पर कितने बाइट्स को पढ़ने के लिए यह देखने की उम्मीद करते हुए लेन परिवर्तनीय (59kb फ़ाइल पढ़ते समय) की निगरानी की। आईई और फ़ायरफ़ॉक्स में, 18kb पर, in.read (buf) एक -1 देता है जैसे फ़ाइल समाप्त हो गई है। सफारी ऐसा नहीं करता है।

मैं इसे रखूंगा, और अब तक मैं सभी सुझावों की सराहना करता हूं।

+0

जब आप कहते हैं कि फ़ाइल दूषित है, आप वास्तव में क्या मतलब है? यदि आप मूल की तुलना करते हैं, तो अलग क्या है? – Eddie

+0

एडी के प्रश्न के 2 भाग के उत्तर दें। साथ ही, सामग्री लम्बाई का मूल्य सही है? – jdigital

उत्तर

11

बस मामले में इन छोटे परिवर्तन एक फर्क है, इस प्रयास करें:

public static ByteBuffer getAsByteArray(URL url) throws IOException { 
    URLConnection connection = url.openConnection(); 
    // Since you get a URLConnection, use it to get the InputStream 
    InputStream in = connection.getInputStream(); 
    // Now that the InputStream is open, get the content length 
    int contentLength = connection.getContentLength(); 

    // To avoid having to resize the array over and over and over as 
    // bytes are written to the array, provide an accurate estimate of 
    // the ultimate size of the byte array 
    ByteArrayOutputStream tmpOut; 
    if (contentLength != -1) { 
     tmpOut = new ByteArrayOutputStream(contentLength); 
    } else { 
     tmpOut = new ByteArrayOutputStream(16384); // Pick some appropriate size 
    } 

    byte[] buf = new byte[512]; 
    while (true) { 
     int len = in.read(buf); 
     if (len == -1) { 
      break; 
     } 
     tmpOut.write(buf, 0, len); 
    } 
    in.close(); 
    tmpOut.close(); // No effect, but good to do anyway to keep the metaphor alive 

    byte[] array = tmpOut.toByteArray(); 

    //Lines below used to test if file is corrupt 
    //FileOutputStream fos = new FileOutputStream("C:\\abc.pdf"); 
    //fos.write(array); 
    //fos.close(); 

    return ByteBuffer.wrap(array); 
} 

आप fos जो कि फ़ाइल में कम किया जा रहा है, तो आपके आवेदन अभी भी चल रहा है या अचानक समाप्त हो जाता है में हो सकता है बंद करने के लिए भूल गया था। इसके अलावा, मैंने उपयुक्त प्रारंभिक आकार के साथ ByteArrayOutputStream बनाने को जोड़ा। (अन्यथा जावा को बार-बार एक नई सरणी आवंटित करना होगा और प्रतिलिपि बनाना होगा, एक नई सरणी आवंटित करें और कॉपी करें, जो महंगा है।) मान 16384 को अधिक उपयुक्त मान के साथ बदलें। 16k शायद पीडीएफ के लिए छोटा है, लेकिन मुझे नहीं पता कि कैसे "औसत" आकार यह है कि आप डाउनलोड करने की उम्मीद करते हैं।

चूंकि आप toByteArray() दो बार उपयोग करते हैं (भले ही कोई डायग्नोस्टिक कोड में है), मैंने इसे एक चर के लिए असाइन किया है। आखिरकार, हालांकि, यदि आप बाइटबफर में संपूर्ण सरणी को लपेट रहे हैं, तो आपको कोई अंतर नहीं करना चाहिए, आपको केवल बाइट सरणी की आपूर्ति करने की आवश्यकता है। ऑफसेट 0 की आपूर्ति और लंबाई अनावश्यक है।

ध्यान दें कि अगर आप बड़े पीडीएफ फाइलों इस तरह से डाउनलोड कर रहे हैं, तो सुनिश्चित करें कि आपके JVM एक बड़ा पर्याप्त ढेर आप कई बार सबसे बड़ा फ़ाइल आकार आप को पढ़ने के लिए उम्मीद के लिए पर्याप्त जगह है कि के साथ चल रहा है। जिस विधि का आप उपयोग कर रहे हैं वह पूरी फ़ाइल को स्मृति में रखता है, जो तब तक ठीक है जब तक आप उस स्मृति को बर्दाश्त कर सकें।:)

0

क्या आपने को tmpOut स्ट्रीम बंद करने से पहले सभी बाइट्स को सुनिश्चित करने के लिए प्रयास किया है?

+1

पास() एक फ्लश करता है() – jdigital

0

आप पूरी तरह सकारात्मक इस कोड IOExceptions है कि आप नहीं देख रहे हैं, क्योंकि उन पर इस विधि या कुछ इस तरह का फोन करने वाले से उपेक्षा फेंक नहीं है कर रहे हैं? जैसा कोड मुझे अच्छा लगता है।

0

Fiddler (एक मुफ्त HTTP डीबगिंग प्रॉक्सी) चलाने का प्रयास करें और देखें कि कुछ दिलचस्प दिखाता है - जाहिर है आप यह सुनिश्चित करना चाहते हैं कि सर्वर पूर्ण स्ट्रीम भेज रहा है, लेकिन आप सामग्री-लंबाई की जांच भी करना चाहेंगे आदि। आप किसी भी ब्राउज़र के साथ फिडलर का उपयोग कर सकते हैं लेकिन मैं आईई का उपयोग करता हूं क्योंकि प्रॉक्सी स्वचालित रूप से कॉन्फ़िगर किया जाएगा।

0

मैंने सोचा कि मुझे आपके जैसा ही समस्या है, लेकिन यह पता चला कि मेरी समस्या यह थी कि मुझे लगता है कि जब तक आपको कुछ भी नहीं मिलता तब तक आपको हमेशा पूर्ण बफर मिलता है। लेकिन आप इसे नहीं मानते हैं। शुद्ध (जैसे java2s/tutorial) पर उदाहरण एक BufferedInputStream का उपयोग करें। लेकिन इससे मेरे लिए कोई फर्क नहीं पड़ता है।

आप की जांच कर सकता है कि क्या आप वास्तव में अपने पाश में पूर्ण फ़ाइल मिलता है। समस्या से अधिक ByteArrayOutputStream में होगा।

संबंधित मुद्दे