سؤال

أنا جديدة للغاية جافا ، مجرد تعليم نفسي أذهب ، حتى لقد بدأ بناء الصغير.أود أن يجعل واحدة التي يمكن أن حدد الملف من القرص المحلي وتحميله كما multipart/form-data بعد طلب ولكن مع شريط التقدم.ومن الواضح أن المستخدم قد منح الإذن Java الوصول إلى القرص الثابت.الآن كنت قد حصلت بالفعل الجزء الأول العامل:يمكن للمستخدم تحديد الملف باستخدام JFileChooser الكائن الذي ملائم ترجع File الكائن.ولكن أنا أتساءل ما يأتي المقبل.وأنا أعلم أن File.length() سوف تعطيني إجمالي حجم بايت من الملف ولكن كيف يمكنني إرسال المحدد File على شبكة الإنترنت, وكيف يمكنني رصد عدد البايتات تم إرسالها ؟ شكرا مقدما.

هل كانت مفيدة؟

المحلول 3

انتهى عثرة عبر مفتوح المصدر جافا رافع الصغير و وجدت كل ما كنت بحاجة إلى معرفة داخل التعليمات البرمجية الخاصة به.وهنا وصلات إلى بلوق وظيفة واصفا إياه وكذلك المصدر:

المادة
التعليمات البرمجية المصدر

نصائح أخرى

للتحقق من التقدم المحرز باستخدام 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);
        }
    }
}

ثم تنفذ ProgressListener التي تحديثات شريط التقدم.
تذكر أن شريط التقدم التحديث يجب أن لا تعمل على ترابط إرسال الحدث.

أبسط 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));
    }
}

كمية من وحدات البايت التي تم إرجاعها من قبل المستمع مختلفة من حجم الملف الأصلي.لذا بدلا من وجود 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);
}

قد تجد هذا المادة مفيدا.وهذا ما يفسر بالتفصيل باستخدام HttpClient و FileUpload ، سواء أباتشي المشاريع أن تفعل ما تريد.كما يتضمن نماذج التعليمات البرمجية.

نضع في اعتبارنا أن شريط التقدم قد يكون مضللا عندما وسيطة عنصر في الشبكة (مثل مزود خدمة الإنترنت HTTP proxy, أو عكس وكيل HTTP أمام server) يستهلك الخاص بك تحميل أسرع من الخادم.

كما أشار المقال فنسنت نشر ، يمكنك استخدام Apache العموم للقيام بذلك.

قليلا مقصوص


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

فقط 2c يستحق:

هذا هو أساس الخروج من tuler الجواب(لديه علة في وقت كتابة التقرير).انا عدلت عليه قليلا, حتى هنا هو بلدي نسخة من tuler و mmyers الإجابة (لا أستطيع تحرير الجواب).أردت أن محاولة لجعل هذا قليلا أنظف وأسرع.إلى جانب الأخطاء(التي أناقش في تعليق على الجواب) ، مشكلة كبيرة لدي مع النسخة الخاصة هو أنه يخلق جديد CountingOutputStream مع كل كتابة.هذا يمكن الحصول على مكلفة جدا من حيث الذاكرة - طن من المخصصات القمامة مجموعات.أصغر المسألة هو أن يستخدم مندوب عند ذلك فقط يمكن توسيع MultipartEntity.غير متأكد لماذا اختاروا ذلك ، إذا فعلت ذلك بطريقة كنت أكثر دراية.إذا كان أي شخص يعرف إيجابيات/سلبيات من اثنين من الأساليب التي من شأنها أن تكون كبيرة.وأخيرا ، FilterOutputStream#كتابة(byte[], int,int) الطريقة فقط يدعو FilterOutputStream#كتابة(بايت) في حلقة.على FOS الوثائق توصي فرعية تجاوز هذا السلوك مما يجعل هذا أكثر كفاءة.أفضل طريقة للقيام بذلك هنا هو السماح الأساسية OutputStream التعامل مع كتابة الطلب.

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

ننظر إلى عميل HTTP بالنسبة uploadign الملف إلى ويب.يجب أن تكون قادرة على القيام بذلك.أنا غير متأكد من كيفية الحصول على شريط التقدم, ولكن ذلك ينطوي على الاستعلام عن واجهة برمجة التطبيقات بطريقة أو بأخرى.

أباتشي شيوعا هو خيار جيد جدا.أباتشي مشترك يسمح لك لتكوين الأمور التالية.

  1. تكوين(ملف xml) أقصى حجم الملف/ تحميل حجم الملف
  2. مسار الوجهة (مكان حفظ الملف الذي تم تحميله)
  3. تعيين درجة الحرارة.المجلد لمبادلة الملف ، بحيث تحميل الملف سيكون سريع.

من إجابات أخرى يمكنك فقط تجاوز AbstractHttpEntity فئة الأطفال أو تطبيقات public void writeTo(OutputStream outstream) الأسلوب الذي تستخدمه إذا لم ترغب في إنشاء فئة.

مثال باستخدام 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]
            }
        });
    }

};
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top