Multipart HTTP 表单提交器 - 带进度信息






3.43/5 (6投票s)
从 Java 提交 multipart HTTP 请求并显示上传进度信息。

引言
在我的一个项目中,我需要能够使用 HTTP 将数据提交到 Web 服务器。 问题是这些数据是 multipart 格式的,也就是说,是二进制数据和文本数据的组合。 因此,简单的 GET
或 POST
调用是不够的。 Vlad Patryshev 的 ClientHTTPRequest
类帮我解决了这个问题。 这个功能强大的类允许您轻松地通过 HTTP 提交 multipart 格式的数据。 但是,它缺少一件事:进度信息。 也就是说,当通过 HTTP 发送大型文件时,用户需要知道已经发送了多少文件,还有多少文件需要发送。 因此,我扩展了 Vlad 的类,以提供上传进度信息。
背景
为了更好地理解使用此类的方法和背后的思想,我建议阅读 Vlad 关于他的类 ClientHTTPRequest
的文章。 您可以在这里找到这篇文章。
现在,我修改了这个类,通过以下更改来提供进度信息
- 推迟建立 HTTP 连接,直到实际的发布发生 – 原始类在调用
write()
函数时立即连接。 在此版本中,调用write
函数,但不建立连接。 - 所有
write()
调用都导致数据写入到ByteArrayOutputStream
,而不是直接写入连接的OutputStream
。 这样做是因为需要提前知道 content-length(在实际通过套接字流式传输数据之前),以便提供进度信息,并且为了使用连接的特殊setFixedLengthStreamingMode
模式
…ByteArrayOutputStream baos = new ByteArrayOutputStream(); protected void write(char c) throws Exception { baos.write(c); } protected void write(String s) throws Exception { baos.write(s.getBytes()); }
- 仅当调用
post()
时,才会创建 HTTP 连接。 此连接被赋予setFixedLengthStreamingMode
设置。 然后,baos
(写入所有内容的ByteArrayOutputStream
)的内容以每次 50 KB 的增量输送到 HTTP 连接输出流中。 - 同样值得一提的是添加了
SubmitProgress
接口,该接口用于使该类的客户端能够接收以下进度回调
public interface SubmitProgress { //called every 50KB of transfer to report how much was transferred so far public void bytesTransferred(long bytes); //tells the client how many bytes will actually get transferred. //Useful to set a progress bar’s top limit (setMaximum()). public void setBytesToTransfer(long bytes); //provides the current status of the operation public void statusMessage(String status); //called when the upload has been completed. public void transferComplete(); }
Using the Code
要使用此代码,您需要在项目中包含ClientHTTPRequest2.java 和 SubmitProgress.java。 您还需要实现 SubmitProgress
接口,以便接收有关上传的进度信息。 请注意,您可以设置 HTTP 参数(以后可以由您的 servlet/cgi 代码检索,就像 Web 浏览器将它们放置在 URL 查询中一样),当然,您也可以将整个文件附加到请求中。 例如,下面的代码段显示了如何提交文件和 2 个参数:user
和 password
。
ClientHttpRequest2 chr=new ClientHttpRequest2(submitUrl);
//csp is an implementation of the SubmitProgress Interface.
chr.setSubmitProgress(csp);
chr.setParameter("user",user);
chr.setParameter("password",password);
chr.setParameter("filename",new File(filename));
上面的代码将向 submitUrl
指向的 Web 服务器发送 HTTP 请求。 此请求将具有参数 user
、password
并且还将向服务器提交文件 “filename
” 的内容。(注意:服务器需要知道如何解析数据的 multipart 格式)。 进度信息将通过 SubmitProgress
接口提供。 例如,方法 SubmitProgress.bytesTransferred(long bytes)
将被定期调用以通知已传输了多少字节。
该演示程序(可与本文一起下载)会向 localhost URL 上的服务器执行提交。 您应该将该 URL 更改为在远程运行的 Web 服务器,并且如果与其的连接速度相对较慢,例如 DSL,您将会看到上传进度。 要运行演示,只需编译所有文件 (javac *.java
) 并运行 Main.java 文件 (java Main
)。 然后,在出现的框架上,单击“选择文件”。 您应该选择一个大文件。 然后,按钮将更改为“上传文件”。 按下它,文件 + 两个参数将被上传。 此演示中的类 DemoFrame
是如何实现 SubmitProgress
接口以获取进度信息的一个很好的例子。
历史
- 2006 年 1 月 27 日:版本 1.0