2

我看了 HttpClient 进度代码,但我仍然有问题找不到答案 在哪里获取此 ProgressListener 以放置构造函数参数?以及如何正确使用代码?请帮忙

这是代码

import java.io.FilterOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.nio.charset.Charset;
import org.apache.http.entity.mime.HttpMultipartMode;
import org.apache.http.entity.mime.MultipartEntity;

public class CountingMultipartEntity extends MultipartEntity {

    private final ProgressListener listener;

    public CountingMultipartEntity(final ProgressListener listener) {
        super();
        this.listener = listener;
    }

    public CountingMultipartEntity(final HttpMultipartMode mode, final ProgressListener listener) {
        super(mode);
        this.listener = listener;
    }

    public CountingMultipartEntity(HttpMultipartMode mode, final String boundary,
            final Charset charset, final ProgressListener listener) {
        super(mode, boundary, charset);
        this.listener = listener;
    }

    @Override
    public void writeTo(final OutputStream outstream) throws IOException {
        super.writeTo(new CountingOutputStream(outstream, 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);
        }
    }
}

我可以实现这样的接口吗?

...
public static interface ProgressListener {
        void transferred(long num);
    }
    public static class Progress implements ProgressListener
    {

      public void transferred(long num) {
//            // update the progress bar or whatever else you might want to do

        }

    }
...

但是对于这个包含 HttpClient 的外部类,我该如何初始化 ProgressListener 呢?

CountingMultiPartEntity entity = new CountingMultiPartEntity(new ProgressListener() {

        public void transferred(long num) {
            // update the progress bar or whatever else you might want to do
        }
    });
4

3 回答 3

2

ProgressListener如果您还没有任何实现接口的类,则需要自己构建接口的实现。对于像监听器这样的东西,这通常是通过一个匿名的内部类来完成的。

CountingMultipartEntity entity = new CountingMultipartEntity(new ProgressListener() {
    @Override
    public void transferred(long num) {
        // update the progress bar or whatever else you might want to do
    }
});
于 2011-03-16T03:07:03.060 回答
0

您应该将 ProgressListener 导入您要调用的类

import com.blahblah.YourProjectName.CustomMultipartEntity.ProgressListener;

我正在使用一个名为“CustomMultipartEntity”的类似类,不要忘记更改它的名称。

CustomMultipartEntity 类的实现是:

package com.blahblah.YourProjectName;
import java.io.FilterOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.nio.charset.Charset;
import org.apache.http.entity.mime.HttpMultipartMode;
import org.apache.http.entity.mime.MultipartEntity;
public class CustomMultipartEntity extends MultipartEntity
{


private final ProgressListener listener;

public CustomMultipartEntity(final ProgressListener listener)
{
    super();
    this.listener = listener;
}

public CustomMultipartEntity(final HttpMultipartMode mode, final ProgressListener listener)
{
    super(mode);
    this.listener = listener;
}

public CustomMultipartEntity(HttpMultipartMode mode, final String boundary, final Charset charset, final ProgressListener listener)
{
    super(mode, boundary, charset);
    this.listener = listener;
}

@Override
public void writeTo(final OutputStream outstream) throws IOException
{
    super.writeTo(new CountingOutputStream(outstream, 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);
    }
}
}

这是一个示例调用:

CustomMultipartEntity reqEntity = new CustomMultipartEntity(new ProgressListener() {

                    public void transferred(long num) {
                        if((int) ((num / (float) totalSize) * 100) > 0)
                            progressHandler(num);
                    }
                });
于 2012-09-20T08:13:47.623 回答
0

我在这里找到了这个:https ://www.baeldung.com/httpclient-post-http-request#get-file-upload-progress

这个想法是,在您(通常)创建实体之后,将其包装到另一个实体中,同时指定一个侦听器对象,该对象将在字节传输到远程主机时收到通知。在基本示例中,此通知仅包含一个百分比(传输的字节数 / 总字节数 * 100),但您可以扩展它以满足您的需要。

为了完整起见,这是上面链接中列出的代码:

你从一个界面开始:

public interface ProgressListener {
    void progress(float percentage);
}

接下来你有实体包装器:

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

public class ProgressEntityWrapper extends HttpEntityWrapper {
    private ProgressListener listener;

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

    @Override
    public void writeTo(OutputStream outstream) throws IOException {
        super.writeTo(new CountingOutputStream(outstream, listener, getContentLength()));
    }
}

最后你有输出流,它跟踪进度:

public class CountingOutputStream extends FilterOutputStream {
    private ProgressListener listener;
    private long transferred;
    private long totalBytes;

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

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

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

    private float getCurrentProgress() {
        return ((float) transferred / totalBytes) * 100;
    }
}

免责声明:以上内容只是从上述链接复制/粘贴。(同时添加一些导入和删除static修饰符)

这对我来说效果很好。请务必Content-Length在您的响应中指定一个标头,否则该值totalBytes将是-1,这将导致计算失败。

专业提示:您可以通过以精确度为代价发送更少的通知来稍微优化一下。我会尝试这样的事情:

public CounterOutputStream(OutputStream out, ProgressListener listener, long totalBytes) {
    super(out);
    final ProgressListener xl = listener;
    this.listener = new ProgressListener() {
        private int p = 0;

        @Override
        public void progress(float percentage) {
            if (Math.floor(percentage) > p) {
                p = (int) percentage;
                xl.progress(percentage);
            }
        }
    };
    transferred = 0;
    this.totalBytes = totalBytes;
}

另一个免责声明:我实际上并没有测试上述新版本的构造函数CounterOutputStream

您可以像这样使用所有这些:

HttpEntity entity = MultipartEntityBuilder.create()
  .setMode(HttpMultipartMode.RFC6532)
  .addTextBody("Part1", "Some text", Constants.CT_U8_TEXT)
  .addTextBody("Part2", moreText, Constants.CT_U8_TEXT)
  .addTextBody("Part3", someVariable, Constants.CT_U8_TEXT)
  .build()
;

// This instruction here:
entity = new ProgressEntityWrapper(
  entity
  , percentage -> LOG.info("Upload at: " + percentage)
);

HttpUriRequest post = RequestBuilder
  .post(url)
  .setEntity(entity)
  .build()
;

// etc...
于 2021-11-11T14:44:48.277 回答