문제

나는 매우 새로운 Java에게, 그리고 내가 갈 때 주로 자신을 가르치고 있었기 때문에 애플릿을 만들기 시작했습니다. 로컬 디스크에서 파일을 선택하고이를 멀티 파트/양식 데이터 게시물 요청으로 업로드 할 수있는 파일을 만들고 싶습니다. 진행률 바와 함께. 분명히 사용자는 하드 드라이브에 액세스하기 위해 Java 애플릿에 권한을 부여해야합니다. 이제 이미 첫 번째 부분이 작동했습니다. 사용자는 다음을 사용하여 파일을 선택할 수 있습니다. JFileChooser 편리하게 반환하는 객체 a File 물체. 그러나 나는 다음에 무엇이 오는지 궁금합니다. 나는 그것을 알고있다 File.length() 파일의 바이트로 총 크기를 줄 것이지만 선택한 것을 어떻게 보내나요? File 웹에, 그리고 몇 바이트 수를 보냈는지 어떻게 모니터링합니까? 미리 감사드립니다.

도움이 되었습니까?

해결책 3

결국 오픈 소스 Java 업 로더 애플릿을 가로 질러 넘어져 코드 내에서 알아야 할 모든 것을 발견했습니다. 다음은 소스뿐만 아니라 블로그 게시물에 대한 링크입니다.

기사
소스 코드

다른 팁

httpclient를 사용하여 진행 상황을 확인하려면 전송되는 바이트를 계산하는 다중 관점을 감싸십시오. 래퍼는 다음과 같습니다.

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를 구현합니다.
진행률 표시 줄 업데이트는 이벤트 디스패치 스레드에서 실행되지 않아야합니다.

더 간단한 계수는 특정 엔티티 유형에 의존하지 않고 오히려 확장됩니다. 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를 사용하여 자세히 설명합니다. 두 아파치 프로젝트는 원하는 작업을 수행합니다. 또한 코드 샘플도 포함되어 있습니다.

네트워크의 중간 구성 요소 (예 : ISP의 HTTP 프록시 또는 서버 앞의 역 HTTP 프록시)가 서버보다 업로드를 더 빨리 소비하면 진행률 표시 줄이 오도 될 수 있습니다.

Vincent가 게시 한 기사에서 언급했듯이 Apache Commons를 사용하여이를 수행 할 수 있습니다.

작은 딱딱한


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#Writ 그만큼 FOS 문서 이 동작을 무시하고 더 효율적으로 만드는 서브 클래스를 권장합니다. 여기서 그렇게하는 가장 좋은 방법은 기본 출력 스트림이 쓰기 요청을 처리하도록하는 것입니다.

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 클라이언트 파일을 웹에 업로드하기 위해. 그렇게 할 수 있어야합니다. 진행률 표시 줄을 얻는 방법은 확실하지 않지만 API를 어떻게 든 쿼리하는 것이 포함됩니다.

Apache Common은 매우 좋은 옵션입니다. Apache Common을 사용하면 다음을 구성 할 수 있습니다.

  1. 구성 (XML 파일) 최대 파일 크기/ 파일 크기 업로드
  2. 대상 경로 (업로드 된 파일을 저장하는 위치)
  3. 온도를 설정하십시오. 파일 업로드가 빠르도록 파일을 바꾸는 폴더.

다른 답변에서 당신은 단지 그것을 무시할 수 있습니다 AbstractHttpEntity 수업 어린이 또는 구현 public void writeTo(OutputStream outstream) 클래스를 만들고 싶지 않은 경우 사용중인 방법.

a를 사용하는 예 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