最近在开发时遇到需要上传文件的功能,我自然而然地上网找了段实现上传功能的代码。我的程序有两个地方需要上传文件,这段代码在一处能用,另一处就报错了。代码如下:
File file = new File( "文件路径" );
MultipartEntityBuilder builder = MultipartEntityBuilder.create();
builder.setMode(HttpMultipartMode.BROWSER_COMPATIBLE);
builder.setBoundary("---------------------------7e5db2ac0ab0");
builder.addBinaryBody("abc",new FileInputStream(file) , ContentType.APPLICATION_OCTET_STREAM, file.getName());//
httpPost.setEntity(builder.build());
HttpResponse response = client.execute(httpPost);
这段代码请留意 builder.addBinaryBody 的第二个参数,它的类型是流。这段代码在另一处运行时,会得到如下返回:
411 Length Required
Length Required
A request of the requested method POST requires a valid Content-length.
意思是说,请求头需要有Content-length字段。同一段代码,一处正常一处异常,这就让人很恼火了,而且排查也不太容易。这问题耗了我快两天时间,最后我从底层抛异常的源码慢慢地排查才发现,builder.addBinaryBody 的第二个参数如果是File类型,在请求报文的头部会自动生成Content-length字段并自动计算和赋值!
后来代码改为:
builder.addBinaryBody("filename",file , ContentType.APPLICATION_OCTET_STREAM, file.getName());
//第二个参数直接传入File类型对象。
后来我对自己遇到这问题后整个解决过程作了回顾。一开始觉得很莫名奇妙,因为同样的代码一处成功另一处失败,但是当时不管那么多了,就根据响应信息,人为地在请求报文头部添加Content-length这段。但随后直接报异常,大意是不能重复加这个字段。这时顿感万分尴尬,不知如何是好。更要命的是,在网上也找不到解决我这问题的文章。最后,在无何奈何之下,重新整理心情,从源代码入手,慢慢顺藤摸瓜地一层一层往上查源码,最后才发现原来有另一个接口可用。
最后总结。在开发过程中,我们在网上摘取代码无可厚非,然而这些代码不一定完全适用。我们必须有足够的心理准备。一旦运行结果不是我们预期的时候,翻查源码是可选项之一。当运行结果不符合预期时,我们必须冷静分析,一个是根据错误提示排查;另一个大不了翻查源码,只要有信心和耐心一定能够查出原因。