泽西客户端上传进度

Ago*_*noX 8 java upload jersey

我有一个球衣客户端需要上传一个足够大的文件来要求进度条.
问题是,对于需要几分钟的上传,我看到一旦应用程序启动,转移的字节就会变为100%.然后打印"完成"字符串需要几分钟.
就好像字节被发送到一个缓冲区,我正在读取transfert到缓冲区的速度而不是实际的上传速度.这使得进度条无用.

这是非常简单的代码:

ClientConfig config = new DefaultClientConfig();
Client client = Client.create(config);
WebResource resource = client.resource("www.myrestserver.com/uploads");
WebResource.Builder builder = resource.type(MediaType.MULTIPART_FORM_DATA_TYPE);

FormDataMultiPart multiPart = new FormDataMultiPart();
FileDataBodyPart fdbp = new FileDataBodyPart("data.zip", new File("data.zip"));
BodyPart bp = multiPart.bodyPart(fdbp);
String response = builder.post(String.class, multiPart);
Run Code Online (Sandbox Code Playgroud)

为了获得进展状态,我在调用builder.post之前添加了一个ContainerListener过滤器.

final ContainerListener containerListener = new ContainerListener() {

        @Override
        public void onSent(long delta, long bytes) {
            System.out.println(delta + " : " + long);
        }

        @Override
        public void onFinish() {
            super.onFinish();
            System.out.println("on finish");
        }

    };

    OnStartConnectionListener connectionListenerFactory = new OnStartConnectionListener() {
        @Override
        public ContainerListener onStart(ClientRequest cr) {
            return containerListener;
        }

    };

    resource.addFilter(new ConnectionListenerFilter(connectionListenerFactory));
Run Code Online (Sandbox Code Playgroud)

Tom*_*żak 3

为 java.io.File 提供自己的 MessageBodyWriter 应该足够了,它会在进度更改时触发一些事件或通知一些侦听器

@Provider()
@Produces(MediaType.APPLICATION_OCTET_STREAM)
public class MyFileProvider implements MessageBodyWriter<File> {

    public boolean isWriteable(Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType) {
        return File.class.isAssignableFrom(type);
    }

    public void writeTo(File t, Class<?> type, Type genericType, Annotation annotations[], MediaType mediaType, MultivaluedMap<String, Object> httpHeaders, OutputStream entityStream) throws IOException {
        InputStream in = new FileInputStream(t);
        try {
            int read;
            final byte[] data = new byte[ReaderWriter.BUFFER_SIZE];
            while ((read = in.read(data)) != -1) {
                entityStream.write(data, 0, read);
                // fire some event as progress changes
            }
        } finally {
            in.close();
        }
    }

    @Override
    public long getSize(File t, Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType) {
        return t.length();
    }
}
Run Code Online (Sandbox Code Playgroud)

并让您的客户端应用程序简单地使用这个新的提供程序:

ClientConfig config = new DefaultClientConfig();
config.getClasses().add(MyFileProvider.class);
Run Code Online (Sandbox Code Playgroud)

或者

ClientConfig config = new DefaultClientConfig();
MyFileProvider myProvider = new MyFileProvider ();
cc.getSingletons().add(myProvider);
Run Code Online (Sandbox Code Playgroud)

您还必须包含一些算法来识别接收进度事件时传输的文件。

编辑:

我刚刚发现默认情况下 HTTPUrlConnection 使用缓冲。要禁用缓冲,您可以执行以下操作:

  1. httpUrlConnection.setChunkedStreamingMode(chunklength) - 禁用缓冲并使用分块传输编码发送请求
  2. httpUrlConnection.setFixedLengthStreamingMode(contentLength) - 禁用缓冲,但对流式传输施加一些限制:必须发送确切的字节数

所以我建议您问题的最终解决方案使用第一个选项,如下所示:

ClientConfig config = new DefaultClientConfig();
config.getClasses().add(MyFileProvider.class);
URLConnectionClientHandler clientHandler = new URLConnectionClientHandler(new HttpURLConnectionFactory() {
     @Override
     public HttpURLConnection getHttpURLConnection(URL url) throws IOException {
           HttpURLConnection connection = (HttpURLConnection) url.openConnection();
                connection.setChunkedStreamingMode(1024);
                return connection;
            }
});
Client client = new Client(clientHandler, config);
Run Code Online (Sandbox Code Playgroud)