泽西客户端上传进度 [英] Jersey client upload progress
问题描述
我有一个球衣客户端,需要上传一个足够大的文件才能要求进度条。
问题是,对于需要几分钟的上传,我看到转移的字节数去了应用程序启动后立即100% 。然后打印on finished字符串需要几分钟。
就像字节被发送到缓冲区一样,我正在读取transfert到缓冲区的速度而不是实际的上传速度速度。这使得进度条无用。
I have a jersey client that need to upload a file big enough to require a progress bar.
The problem is that, for an upload that requires some minutes, i see the bytes transfered to go to 100% as soon as the application has started. Then it takes some minutes to print the "on finished" string.
It is as if the bytes were sent to a buffer, and i was reading the transfert-to-the buffer speed instead of the actual upload speed. This makes the progress bar useless.
这是非常简单的代码:
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);
为了获得进展状态,我在调用builder.post:之前添加了一个ContainerListener过滤器。 p>
To get progress state i've added a ContainerListener filter, obviouslt before calling builder.post:
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));
推荐答案
它应该足以为java提供自己的MessageBodyWriter .io.File会触发某些事件或通知某些听众进度变化
it should be enough to provide you own MessageBodyWriter for java.io.File which fires some events or notifies some listeners as progress changes
@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();
}
}
并让您的客户端应用程序简单地使用这个新的提供者:
and to make your client application uses this new provider simply:
ClientConfig config = new DefaultClientConfig();
config.getClasses().add(MyFileProvider.class);
或
ClientConfig config = new DefaultClientConfig();
MyFileProvider myProvider = new MyFileProvider ();
cc.getSingletons().add(myProvider);
您还必须包含一些算法来识别接收进度事件时传输的文件。
You would have to also include some algorithm to recognize which file is transfered when receiving progress events.
编辑:
我发现默认情况下HTTPUrlConnection使用缓冲。要禁用缓冲,你可以做几件事:
I just found that by default HTTPUrlConnection uses buffering. And to disable buffering you could do couple of things:
- httpUrlConnection.setChunkedStreamingMode(chunklength) - 禁用缓冲并使用分块传输编码发送请求
- httpUrlConnection.setFixedLengthStreamingMode(contentLength) - 禁用缓冲,但会对流式传输一些约束:必须发送确切的字节数
所以我建议你的问题的最终解决方案使用第一个选项,看起来像这样:
So I suggest the final solution to your problem uses 1st option and would look like this:
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);
这篇关于泽西客户端上传进度的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!