2008-10-31 22 views
29

मैं जावा पर बेहद नया हूं, और ज्यादातर मेरे जैसे ही पढ़ रहा हूं, इसलिए मैंने एक एप्लेट बनाना शुरू कर दिया है। मैं एक ऐसा बनाना चाहता हूं जो स्थानीय डिस्क से फ़ाइल का चयन कर सके और इसे एक मल्टीपार्ट/फॉर्म-डेटा पोस्ट अनुरोध के रूप में अपलोड करें लेकिन प्रगति पट्टी के साथ अपलोड करें। स्पष्ट रूप से उपयोगकर्ता को हार्ड ड्राइव तक पहुंचने के लिए जावा एप्लेट को अनुमति देना है। अब मुझे पहले भाग मिल रहा है: उपयोगकर्ता JFileChooser ऑब्जेक्ट का उपयोग कर फ़ाइल का चयन कर सकता है, जो आसानी से File ऑब्जेक्ट देता है। लेकिन मैं सोच रहा हूं कि आगे क्या आता है। मुझे पता है कि File.length() मुझे फ़ाइल के बाइट्स में कुल आकार देगा, लेकिन मैं वेब पर चयनित File कैसे भेजूं, और मैं कैसे निगरानी करूं कि कितने बाइट भेजे गए हैं? अग्रिम में धन्यवाद। वेब के लिए फ़ाइल uploadign के लिए HTTP Client मेंजावा के साथ फ़ाइल अपलोड करें (प्रगति पट्टी के साथ)

+9

यह सिर्फ एक पक्ष टिप्पणी है, मुझे इससे नफरत है जब कंपनियां एप्लेट का प्रयोग कर एक बेहतर अपलोड इंटरफेस और html में एक प्रदान करने के लिए। मुझे लगता है कि यह एक वेब ब्राउज़र मुद्दा है। आप ऐप्पल पर भरोसा नहीं कर सकते हैं जो अनुमति मांगता है, लेकिन अधिकांश उपयोगकर्ता इसे वैसे भी देते हैं। दुखद लेकिन सत्य। – Pyrolistical

+0

@ पेरोलॉजिकल मैं सहमत हूं, लेकिन दुर्भाग्यवश, फ़ाइलों को अपलोड करने के लिए ब्राउज़र समर्थन _still_ भयानक है। यदि आप उन फ़ाइलों पर किसी भी क्लाइंट-साइड प्रोसेसिंग की आवश्यकता/इच्छा में जोड़ते हैं, तो आपके पास एप्लेट या फ्लैश का उपयोग करने के अलावा कोई विकल्प नहीं है। – cdeszaq

उत्तर

6

मैं एक ओपन सोर्स जावा अपलोडर एप्लेट में ठोकर खा गया और मुझे अपने कोड के भीतर जो कुछ जानने की आवश्यकता है उसे मिला। यहाँ एक ब्लॉग पोस्ट के लिए लिंक यह वर्णन के साथ ही स्रोत हैं:

Article
Source Code

1

देखो। यह ऐसा करने में सक्षम होना चाहिए। मुझे यकीन है कि प्रगति पट्टी कैसे प्राप्त करें, लेकिन इसमें किसी भी तरह से एपीआई पूछताछ शामिल होगी।

4

आप इस article लिए उपयोगी हो सकती। यह आप जो चाहते हैं उसे करने के लिए अपाचे परियोजनाओं दोनों, HttpClient और FileUpload का उपयोग करके विस्तार से बताते हैं। इसमें कोड नमूने भी शामिल हैं।

2

लेख विन्सेंट तैनात द्वारा बताया गया है, यदि आप ऐसा करने अपाचे कॉमन्स उपयोग कर सकते हैं।

लिटिल कतरना

 

DiskFileUpload upload = new DiskFileUpload(); 
upload.setHeaderEncoding(ConsoleConstants.UTF8_ENCODING); 

upload.setSizeMax(1000000); 
upload.setSizeThreshold(1000000); 

Iterator it = upload.parseRequest((HttpServletRequest) request).iterator(); 
FileItem item; 
while(it.hasNext()){ 
    item = (FileItem) it.next(); 
    if (item.getFieldName("UPLOAD FIELD"){ 
     String fileName = item.getString(ConsoleConstants.UTF8_ENCODING); 
     byte[] fileBytes = item.get(); 
    } 
} 
 
4

ध्यान रखें कि प्रगति बार गुमराह किया जा सकता है जब नेटवर्क में एक मध्यवर्ती घटक (जैसे, एक आईएसपी के HTTP प्रॉक्सी, या सर्वर के सामने एक रिवर्स HTTP प्रॉक्सी) की खपत सर्वर से तेज़ी से आपका अपलोड करता है।

37

HttpClient का उपयोग कर प्रगति की जाँच करने के लिए, एक बाइट भेजा जा रहा मायने रखता है कि चारों ओर MultipartRequestEntity लपेट दें। रैपर नीचे है:

import java.io.FilterOutputStream; 
import java.io.IOException; 
import java.io.OutputStream; 
import org.apache.commons.httpclient.methods.RequestEntity; 

public class CountingMultipartRequestEntity implements RequestEntity { 
    private final RequestEntity delegate; 

    private final ProgressListener listener; 

    public CountingMultipartRequestEntity(final RequestEntity entity, 
      final ProgressListener listener) { 
     super(); 
     this.delegate = entity; 
     this.listener = listener; 
    } 

    public long getContentLength() { 
     return this.delegate.getContentLength(); 
    } 

    public String getContentType() { 
     return this.delegate.getContentType(); 
    } 

    public boolean isRepeatable() { 
     return this.delegate.isRepeatable(); 
    } 

    public void writeRequest(final OutputStream out) throws IOException { 
     this.delegate.writeRequest(new CountingOutputStream(out, this.listener)); 
    } 

    public static interface ProgressListener { 
     void transferred(long num); 
    } 

    public static class CountingOutputStream extends FilterOutputStream { 

     private final ProgressListener listener; 

     private long transferred; 

     public CountingOutputStream(final OutputStream out, 
       final ProgressListener listener) { 
      super(out); 
      this.listener = listener; 
      this.transferred = 0; 
     } 

     public void write(byte[] b, int off, int len) throws IOException { 
      out.write(b, off, len); 
      this.transferred += len; 
      this.listener.transferred(this.transferred); 
     } 

     public void write(int b) throws IOException { 
      out.write(b); 
      this.transferred++; 
      this.listener.transferred(this.transferred); 
     } 
    } 
} 

फिर प्रोग्रेसलिस्टर लागू करता है जो प्रगति पट्टी को अद्यतन करता है।
याद रखें कि प्रगति बार अद्यतन इवेंट डिस्पैच थ्रेड पर नहीं चलना चाहिए।

+0

क्या आप कृपया प्रोग्रेसलिस्टर का उदाहरण दे सकते हैं जो स्विंग घटकों को अपडेट करेगा – kilonet

+2

क्यों मल्टीपार्टRequestEntity के आसपास countingMultipartRequestEntity को लपेटा जाना चाहिए? – kilonet

+2

दोस्तों, आपका उत्तर गलत है। कई मामलों के लिए, यह भेजे गए सभी बाइट्स को दोगुना कर देगा। FilterOutputStream # लिखें (बाइट [], int, int) बस एक लूप में FOS.write (बाइट) को कॉल करता है, इसलिए आप सभी बाइट्स को गिनती कर रहे हैं। इसके अलावा, एफओएस दस्तावेज़ इस व्यवहार को बदलने की सलाह देते हैं क्योंकि यह कुशल नहीं है। मेरा जवाब देखें, जहां मैं अंतर्निहित धारा को सहेजता हूं और इसे लिखता हूं (बाइट [], int, int) विधि। – Hamy

1

अपाचे आम बहुत अच्छा विकल्प है। अपाचे आम आपको निम्नलिखित चीजों को कॉन्फ़िगर करने की अनुमति देता है।

  1. कॉन्फ़िगर (xml फ़ाइल) अधिकतम फ़ाइल आकार/अपलोड फ़ाइल आकार
  2. गंतव्य पथ (जहां अपलोड की गई फ़ाइल को बचाने के लिए)
  3. अस्थायी सेट करें। फ़ाइल को स्वैप करने के लिए फ़ोल्डर, ताकि फ़ाइल अपलोड तेज हो।
+0

अपाचे कॉमन्स घटकों में से कौन सा? –

2

बस मेरे 2c लायक:

यह tuler के जवाब पर ही आधारित होता (के समय में एक बग है लिख रहे हैं)। मैंने इसे थोड़ा संशोधित किया, इसलिए यहां मेरा ट्यूलर और एमएमएर्स का संस्करण है (मैं उनके जवाब को संपादित नहीं कर सकता)। मैं इसे थोड़ा क्लीनर और तेज़ बनाने का प्रयास करना चाहता था।बग के अलावा (जिसे मैं उनके उत्तर पर टिप्पणियों में चर्चा करता हूं), मेरे संस्करण के साथ मेरे पास बड़ी समस्या यह है कि यह प्रत्येक लेखन के साथ एक नया CountingOutputStream बनाता है। यह स्मृति के मामले में बहुत महंगा हो सकता है - आवंटन और कचरा संग्रह के टन। छोटी समस्या यह है कि एक प्रतिनिधि का उपयोग तब होता है जब यह MultipartEntity का विस्तार कर सकता है। निश्चित नहीं है कि उन्होंने इसे क्यों चुना, इसलिए मैंने इसे इस तरीके से किया जिस तरह से मैं अधिक परिचित था। यदि कोई भी दो दृष्टिकोणों के पेशेवर/विपक्ष को जानता है जो बहुत अच्छा होगा। अंत में, फ़िल्टरऑटपुटस्ट्रीम # लिखें (बाइट [], int, int) विधि केवल लूप में FilterOutputStream # लिखने (बाइट) को कॉल करता है। FOS documentation इस व्यवहार को ओवरराइड करने और इसे और अधिक कुशल बनाने के उप-वर्गों की सिफारिश करता है। ऐसा करने का सबसे अच्छा तरीका अंतर्निहित आउटपुटस्ट्रीम लेखन अनुरोध को संभालने देना है।

import java.io.FilterOutputStream; 
import java.io.IOException; 
import java.io.OutputStream; 

import org.apache.http.entity.mime.HttpMultipartMode; 
import org.apache.http.entity.mime.MultipartEntity; 

public class CountingMultiPartEntity extends MultipartEntity { 

    private UploadProgressListener listener_; 
    private CountingOutputStream outputStream_; 
    private OutputStream lastOutputStream_; 

    // the parameter is the same as the ProgressListener class in tuler's answer 
    public CountingMultiPartEntity(UploadProgressListener listener) { 
     super(HttpMultipartMode.BROWSER_COMPATIBLE); 
     listener_ = listener; 
    } 

    @Override 
    public void writeTo(OutputStream out) throws IOException { 
     // If we have yet to create the CountingOutputStream, or the 
     // OutputStream being passed in is different from the OutputStream used 
     // to create the current CountingOutputStream 
     if ((lastOutputStream_ == null) || (lastOutputStream_ != out)) { 
      lastOutputStream_ = out; 
      outputStream_ = new CountingOutputStream(out); 
     } 

     super.writeTo(outputStream_); 
    } 

    private class CountingOutputStream extends FilterOutputStream { 

     private long transferred = 0; 
      private OutputStream wrappedOutputStream_; 

     public CountingOutputStream(final OutputStream out) { 
      super(out); 
        wrappedOutputStream_ = out; 
     } 

     public void write(byte[] b, int off, int len) throws IOException { 
        wrappedOutputStream_.write(b,off,len); 
        ++transferred; 
      listener_.transferred(transferred); 
     } 

     public void write(int b) throws IOException { 
      super.write(b); 
     } 
    } 
} 
+1

इसमें दूसरे के मुकाबले बहुत अधिक मुद्दे हैं। – ColinD

12

एक सरल countingEntity एक विशिष्ट इकाई प्रकार पर निर्भर करेगा नहीं बल्कि HttpEntityWrapped का विस्तार:

package gr.phaistos.android.util; 

import java.io.FilterOutputStream; 
import java.io.IOException; 
import java.io.OutputStream; 

import org.apache.http.HttpEntity; 
import org.apache.http.entity.HttpEntityWrapper; 

public class CountingHttpEntity extends HttpEntityWrapper { 

    public static interface ProgressListener { 
     void transferred(long transferedBytes); 
    } 


    static class CountingOutputStream extends FilterOutputStream { 

     private final ProgressListener listener; 
     private long transferred; 

     CountingOutputStream(final OutputStream out, final ProgressListener listener) { 
      super(out); 
      this.listener = listener; 
      this.transferred = 0; 
     } 

     @Override 
     public void write(final byte[] b, final int off, final int len) throws IOException { 
      //// NO, double-counting, as super.write(byte[], int, int) delegates to write(int). 
      //super.write(b, off, len); 
      out.write(b, off, len); 
      this.transferred += len; 
      this.listener.transferred(this.transferred); 
     } 

     @Override 
     public void write(final int b) throws IOException { 
      out.write(b); 
      this.transferred++; 
      this.listener.transferred(this.transferred); 
     } 

    } 


    private final ProgressListener listener; 

    public CountingHttpEntity(final HttpEntity entity, final ProgressListener listener) { 
     super(entity); 
     this.listener = listener; 
    } 

    @Override 
    public void writeTo(final OutputStream out) throws IOException { 
     this.wrappedEntity.writeTo(out instanceof CountingOutputStream? out: new CountingOutputStream(out, this.listener)); 
    } 
} 
+0

मैं इसे कैसे कार्यान्वित करूं? आप मुझे टैग अगर आप का जवाब :) –

+0

इस \t \t \t ProgressListener श्रोता की तरह हो सकता है = नए ProgressListener() \t \t \t { \t \t \t \t @Override \t \t \t \t सार्वजनिक शून्य हस्तांतरित (लंबी संख्या) \t \t \t \t { \t \t \t \t parentTask.publicPublish प्रगति (संख्या); \t \t \t \t} \t \t}; \t \t \t स्ट्रिंगएन्टिटी से = नई स्ट्रिंगएन्टिटी (एक्सएमएल); \t \t \t गिनती HttpEntity ce = new countingHttpEntity (se, श्रोता); \t \t \t httppost.setEntity (ce); –

5

श्रोता द्वारा दिया बाइट्स की राशि मूल फ़ाइल आकार से अलग है। तो, transferred++ होने के बजाय, मैंने इसे संशोधित किया ताकि transferred=len; यह आउटपुट स्ट्रीम में लिखे जाने वाले बाइट्स की वास्तविक मात्रा की लंबाई है। और जब मैं गणना की कुल बाइट्स के अलावा हस्तांतरित यह वास्तविक ContentLength अन्य उत्तर से द्वारा CountingMultiPartEntity.this.getContentLength();

public void write(byte[] b, int off, int len) throws IOException { 
    wrappedOutputStream_.write(b,off,len); 
    transferred=len; 
    listener_.transferred(transferred); 
} 
1

लौटे के बराबर है तो आप सिर्फ public void writeTo(OutputStream outstream) विधि आप उपयोग कर रहे हैं नहीं है AbstractHttpEntity वर्ग बच्चों या कार्यान्वयन ओवरराइड कर सकते हैं एक वर्ग बनाना चाहते हैं।

एक FileEntity उदाहरण का उपयोग करते हुए एक उदाहरण:

FileEntity fileEntity = new FileEntity(new File("img.jpg")){ 
    @Override 
    public void writeTo(OutputStream outstream) throws IOException { 
     super.writeTo(new BufferedOutputStream(outstream){ 
      int writedBytes = 0; 

      @Override 
      public synchronized void write(byte[] b, int off, int len) throws IOException { 
       super.write(b, off, len); 

       writedBytes+=len; 
       System.out.println("wrote: "+writedBytes+"/"+getContentLength()); //Or anything you want [using other threads] 
      } 
     }); 
    } 

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