使用RestTemplate.postForLocation实现文件上传进度条

7
我有一个Java桌面客户端应用程序,可以上传文件到REST服务。
所有对REST服务的调用都使用Spring RestTemplate类处理。
我希望实现进度条和取消功能,因为上传的文件可能很大。
我一直在寻找在Web上实现这个功能的方法,但一直没有成功。
我尝试了实现自己的ResourceHttpMessageConverter并替换writeInternal()方法,但是在实际发送请求之前,此方法似乎在某种缓冲操作期间被调用(因此在发送之前流已经全部读取)。
我甚至尝试重写CommonsClientHttpRequestFactory.createRequest()方法,并使用特殊的writeRequest()方法实现自己的RequestEntity类,但是同样的问题仍然存在(在发送post请求之前流已经全部读取)。
我是不是看错了地方?是否有人做过类似的事情。
网络上关于实现进度条的许多文章都谈到启动上传,然后使用单独的AJAX请求轮询Web服务器以获取进度,这似乎是一种奇怪的方式。
非常感谢任何帮助或提示。

这可能是您正在寻找的内容:https://dev59.com/c1XTa4cB1Zd3GeqPzC_n - ams
1
谢谢提供链接。不幸的是,给出的示例使用了低级别的Apache库,因此我不清楚在Spring Rest库中等效的FileBody类是什么,或者我如何注入自己的实现以供它们使用。 - glidester
2个回答

1

这是一个老的问题,但它仍然相关。

我尝试实现自己的ResourceHttpMessageConverter,并替换writeInternal()方法,但是在实际发布请求之前似乎会在某种缓冲操作期间调用此方法(因此在发送之前读取整个流)。

你走对了方向。此外,您还需要禁用RestTemplate的HttpRequestFactory上的请求体缓冲,类似于以下内容:

HttpComponentsClientHttpRequestFactory clientHttpRequestFactory = new HttpComponentsClientHttpRequestFactory();
clientHttpRequestFactory.setBufferRequestBody(false);
RestTemplate restTemplate = new RestTemplate(clientHttpRequestFactory);

这里有一个使用RestTemplate跟踪文件上传进度的工作示例。

谢谢这个信息,听起来就是我想要的。虽然晚了10年,但迟到总比不到好。希望它能帮助其他人。 - glidester

0

关于这个应用程序的具体内容和工作方法并没有太多细节,因此回答比较笼统,但我相信您可以采取类似的方法来跟踪您的上传进度。

如果确实是Java客户端应用程序(即不是HTML / JavaScript而是Java程序),并且您确实将其作为流上传文件,则应该能够通过计算传输缓冲区中传输的数组中的字节数并将其与文件对象的总字节数进行比较来跟踪上传进度。

获取文件并获取其大小。

Integer totalFile = file.getTotalSpace();

无论你在哪里作为流传输,你都应该会向某种输出缓冲区添加字节。

byte[] bytesFromSomeFileReader =  [whatEverYouAreUsingToReadTheFile];

    ByteArrayOutputStream byteStreamToServer = new ByteArrayOutputStream();
    Integer bytesTransmitted = 0;

    for (byte fileByte : bytesFromSomeFileReader) {
        byteStreamToServer.write(fileByte);
            //
            //  Update your progress bar every killo-byte sent.
            //
        bytesTransmitted++;
        if( (bytesTransmitted % 1000) = 0) {
            someMethodToUpdateProgressBar();
        }
    }

抱歉,但这并没有帮助。原则上,这个解决方案是可行的,但正如我在 OP 中所述,似乎在上传开始之前完全读取了流。因此,进度条会飞快地达到100%,然后停留在那里,直到上传完成所需的时间过去。 - glidester
在上传之前如何读取?这是不可能的。正如所述,没有给出任何关于正在进行什么或如何进行的细节。您必须提供实际细节以提供更详细的答案。 - BrianC
如果我们在谈论客户端,那么流应该如何读取?它应该由客户端编写。 - BrianC
我所指的流是本地文件的文件输入流,该文件正在上传到远程服务器。由于这是我两年前参与的项目,我现在无法提供任何详细信息!正如我在原帖中所说,我认为要上传的内容被缓冲,因此在任何网络流量开始之前,流已经完全被读取/写入。因此,我无法使用这些流来实现进度条。 - glidester

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接