Java 如何监控文件上传进度?

Java 如何监控文件上传进度?,java,post,upload,Java,Post,Upload,我需要上传一个文件到服务器,并监测它的进展。 我需要得到一个每次发送多少字节的通知 例如,在下载的情况下,我有: HttpURLConnection connection = (HttpURLConnection) m_url.openConnection(); connection.connect(); InputStream stream = connection.getInputStream(); while ((currentBytes = stream.read(byteBuffe

我需要上传一个文件到服务器,并监测它的进展。 我需要得到一个每次发送多少字节的通知

例如,在下载的情况下,我有:

HttpURLConnection  connection = (HttpURLConnection) m_url.openConnection();
connection.connect();
InputStream stream = connection.getInputStream();
while ((currentBytes  = stream.read(byteBuffer)) > 0) {                    
    totalBytes+=currentBytes;
    //calculate something...
}
现在我需要做同样的上传。但如果使用

OutputStreamWriter stream = new OutputStreamWriter(connection.getOutputStream());
stream.write(str);
stream.flush();
然后我就无法得到任何progres通知,关于发送了多少字节(看起来像是自动操作)

有什么建议吗


谢谢

我在类似情况下所做的是创建一个子类,该子类重写write(…)方法,然后可以通知您的代码任何写入的字节。

如果要计算正在上载的字节,请将对象作为字节数组写入输出流本身,就像您处理输入流一样。

这与您下载的方式类似

OutputStream stream = connection.getOutputStream();
for(byte b: str.getBytes()) {                    
    totalBytes+=1;
    stream.write(b);
    if(totalBytes%50 == 0)
        stream.flush(); //bytes will be sent in chunks of 50
    //calculate something...
}
stream.flush();

类似的情况。

另一种方法是轮询服务器,询问上传了多少数据。也许用身份证什么的

POST->/uploadfile

  • 身份证
  • 文件
POST->/queryuploadstate(返回部分大小)

  • 身份证

当然,它需要连接servlet,并且不允许集群…

我使用了ChannelSocket对象。此对象允许在访问服务器时执行阻塞读写操作。所以我使用这个套接字模拟HTTP,每个写请求都被阻止,直到完成为止。通过这种方式,我可以跟踪写入事务的实际进度。

只需设置分块传输模式并监视您自己对输出流的写入



如果您不使用分块或固定长度传输模式,那么在写入网络之前,您的写入都会写入ByteArrayOutputStream,这样Java就可以正确设置内容长度头。这就是为什么你认为它是非阻塞的。不是的。

嗨。我看到过这样的例子,但也许我不明白。我的意思是,当我写入流时(使用单次写入方法),我确实知道我已经写入了多少字节,但我看不到它的进度。它们可能只在使用flush方法时才会发送到服务器。@Sophie我也有类似的问题。字节被缓存,并且仅在特定时间后写入。如果您知道,可以通过提前设置内容长度来解决此问题-有关详细信息,请参阅HttpURLConnection.setFixedLengthStreamingMode。好的,谢谢,但如果我使用大型文本文件调用write()1次,我将不会看到发送的每个块上的通知,对吗?如果您需要每个字节上的通知,做一些类似于命运之镜给出的答案的事情。一次写入一个字节(或一次写入少量字节)。不,不。理想的做法是通过API向服务器发送每个数据块时获得通知,而不会干扰文件通过网络拆分为数据包的方式。是的,但如果不是我自己偷取的话,这会影响文件的分块方式。调用write并不一定会将这些字节发送到服务器,我需要测量响应时间。根据输出流,您正在写入。然而。。。我可以稍微修改一下…它可以工作,但我仍然希望在发送每个数据包时收到通知,而无需明确配置发送的大小。啊。。。您可能希望编辑您的问题以这样说。添加一些类似“我的问题是,每次发送数据包时,我如何才能收到通知?”这根本不起作用,因为write方法是非阻塞方法,因此无论何时执行实际写入,它都会返回。很遗憾,您没有得到这个问题的真正答案,我很好奇……看来HttpURLConnection不是任务的正确对象。它对输出是非阻塞的,所以我不能用它来衡量性能。我现在正在尝试使用套接字。是的,对于套接字,您可以使用getSendBufferSize来确定它们何时发送数据。这不是“输出无阻塞”@MirroredFate getSendBufferSize()不“确定它们何时发送数据”。它返回一个固定值,除非您自己更改它。它不随发送进度而变化。实际上
connection.setChunkedStreamingMode(2048)成功了。@btoueg“它是用于流媒体的,所以不会按预期工作”为什么?这取决于您的需要。如果你需要上传2Mb~5Mb的文档,流式传输是没有意义的。@BenjaminToueg当然有意义。通过不写入ByteArrayOutputStream,它为您节省了2-5MB内存。您还没有说明为什么它“不能按预期工作”,现在也没有说明2-5MB范围有什么特别之处,或者为什么它只适用于文档。OP想要的是监控文件上传进度。您的答案建议使用分块传输模式。不幸的是,此模式仅适用于流媒体内容。如果您的服务器不支持流式传输,则会出现错误。另一方面,您可以像@Phill建议的那样对outputstream进行子类化,这将使您能够监视上载进度。我想不出有哪种使用案例需要留出2-5MB的内存,除非存在性能问题,而早期优化是万恶之源。顺便说一句,我从来没有说过它只适用于文档。