65.9K
CodeProject 正在变化。 阅读更多。
Home

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

starIconstarIconstarIcon
emptyStarIcon
starIcon
emptyStarIcon

3.43/5 (6投票s)

2006年1月27日

CPOL

3分钟阅读

viewsIcon

41360

downloadIcon

448

从 Java 提交 multipart HTTP 请求并显示上传进度信息。

Sample Image - ClientHTTPRequest2.gif

引言

在我的一个项目中,我需要能够使用 HTTP 将数据提交到 Web 服务器。 问题是这些数据是 multipart 格式的,也就是说,是二进制数据和文本数据的组合。 因此,简单的 GETPOST 调用是不够的。 Vlad Patryshev 的 ClientHTTPRequest 类帮我解决了这个问题。 这个功能强大的类允许您轻松地通过 HTTP 提交 multipart 格式的数据。 但是,它缺少一件事:进度信息。 也就是说,当通过 HTTP 发送大型文件时,用户需要知道已经发送了多少文件,还有多少文件需要发送。 因此,我扩展了 Vlad 的类,以提供上传进度信息。

背景

为了更好地理解使用此类的方法和背后的思想,我建议阅读 Vlad 关于他的类 ClientHTTPRequest 的文章。 您可以在这里找到这篇文章。

现在,我修改了这个类,通过以下更改来提供进度信息

  1. 推迟建立 HTTP 连接,直到实际的发布发生 – 原始类在调用 write() 函数时立即连接。 在此版本中,调用 write 函数,但不建立连接。
  2. 所有 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());
        }
  3. 仅当调用 post() 时,才会创建 HTTP 连接。 此连接被赋予 setFixedLengthStreamingMode 设置。 然后,baos(写入所有内容的 ByteArrayOutputStream)的内容以每次 50 KB 的增量输送到 HTTP 连接输出流中。
  4. 同样值得一提的是添加了 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.javaSubmitProgress.java。 您还需要实现 SubmitProgress 接口,以便接收有关上传的进度信息。 请注意,您可以设置 HTTP 参数(以后可以由您的 servlet/cgi 代码检索,就像 Web 浏览器将它们放置在 URL 查询中一样),当然,您也可以将整个文件附加到请求中。 例如,下面的代码段显示了如何提交文件和 2 个参数:userpassword

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 请求。 此请求将具有参数 userpassword 并且还将向服务器提交文件 “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
© . All rights reserved.