Uploading files – multipart HTTP POST and Apache HttpClient

http://evgeny-goldin.com/blog/uploading-files-multipart-post-apache/


I had to implement a files transferring mechanism where one machine was sending files to another using "multipart/form-data" POST request. It can be done using Apache’s Commons FileUpload andHttpClient.

The receiving part was an easy one:

?
1
2
3
4
5
< dependency >
     < groupid >commons-fileupload</ groupid >
     < artifactid >commons-fileupload</ artifactid >
     < version >1.2.1</ version >
</ dependency >

We parse an incoming request with ServletFileUpload and get a list of FileItems in return. EachFileItem is either form’s input field or a file uploaded:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
if ( ServletFileUpload.isMultipartContent( request ))
{
     List<fileitem> fileItems =
         new ServletFileUpload( new DiskFileItemFactory( 1024 * 1024 , DIR )).
         parseRequest( request );
 
     for ( FileItem item : fileItems )
     {
         String fieldName = item.getFieldName();
 
         if ( item.isFormField()) { item.getString()      } // Form's input field
         else                     { item.getInputStream() } // File uploaded
     }
}

In our case, we use DiskFileItemFactory to store files larger than 1Mb in a temporary DIR. After reading file’s InputStream and storing the data in a proper storage – we need to delete the temporary copy:item.delete().

It’s the sending part that came out to be a bit trickier. Initially, I was using a simple HTML form:

?
1
2
3
4
5
< form action = "http://localhost" method = "post" enctype = "multipart/form-data" >
     < input type = "file" name = "file" >
     < input type = "text" name = "paramName" >
     < input type = "submit" name = "Submit" value = "Upload File" >
</ form >

But then I’ve switched back to Java and assumed HttpClient will do the job.

?
1
2
3
4
5
< dependency >
     < groupid >org.apache.httpcomponents</ groupid >
     < artifactid >httpclient</ artifactid >
     < version >4.0.1</ version >
</ dependency >

Eventually, it did but it took me some time to figure out how. The problem with HttpClient is that it provides a nice tutorial and various usage examples but none of them actually mentions a word about uploading files!

I’ve figured out I need to set an instance of HttpEntity to request but it seemed like it’s going to be either a StringEntity or FileEntity but not both. How come ?! Why is it so hard to send a usual POST request with String and file parameters?

Ok, it’s Google time.

Some examples and documentation were referring to an outdated version when HttpClient was part of Apache Commons and, therefore, were of no use for me – the API has changed dramatically. Until I’ve found this example that finally saved my day. Radomir, thank you!

The solution is to use an additional Apache component – HttpMime:

?
1
2
3
4
5
6
7
8
9
10
11
< dependency >
     < groupid >org.apache.httpcomponents</ groupid >
     < artifactid >httpclient</ artifactid >
     < version >4.0.1</ version >
</ dependency >
 
< dependency >
     < groupid >org.apache.httpcomponents</ groupid >
     < artifactid >httpmime</ artifactid >
     < version >4.0.1</ version >
</ dependency >

and then we finally get to use a magical MultipartEntity:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
HttpClient client = new DefaultHttpClient();
client.getParams().setParameter(CoreProtocolPNames.PROTOCOL_VERSION, HttpVersion.HTTP_1_1);
 
HttpPost        post   = new HttpPost( url );
MultipartEntity entity = new MultipartEntity( HttpMultipartMode.BROWSER_COMPATIBLE );
 
// For File parameters
entity.addPart( paramName, new FileBody((( File ) paramValue ), "application/zip" ));
 
// For usual String parameters
entity.addPart( paramName, new StringBody( paramValue.toString(), "text/plain" ,
                                            Charset.forName( "UTF-8" )));
 
post.setEntity( entity );
 
// Here we go!
String response = EntityUtils.toString( client.execute( post ).getEntity(), "UTF-8" );
 
client.getConnectionManager().shutdown();

Note the use of EntityUtils for reading the response.

That’s it.

I only wish library authors were providing better support and examples for more common cases like files uploading in our case. I mean, come on, when people get to use HttpClient they either want to send a usual request or upload a file, same thing they do with browser. Am I wrong here?


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值