如何使用 Java HttpClient 库与 PHP 一起上传文件
我想编写 Java 应用程序,使用 PHP 将文件上传到 Apache 服务器。 Java 代码使用 Jakarta HttpClient 库版本 4.0 beta2:
import java.io.File;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.HttpVersion;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.FileEntity;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.params.CoreProtocolPNames;
import org.apache.http.util.EntityUtils;
public class PostFile {
public static void main(String[] args) throws Exception {
HttpClient httpclient = new DefaultHttpClient();
httpclient.getParams().setParameter(CoreProtocolPNames.PROTOCOL_VERSION, HttpVersion.HTTP_1_1);
HttpPost httppost = new HttpPost("http://localhost:9002/upload.php");
File file = new File("c:/TRASH/zaba_1.jpg");
FileEntity reqEntity = new FileEntity(file, "binary/octet-stream");
httppost.setEntity(reqEntity);
reqEntity.setContentType("binary/octet-stream");
System.out.println("executing request " + httppost.getRequestLine());
HttpResponse response = httpclient.execute(httppost);
HttpEntity resEntity = response.getEntity();
System.out.println(response.getStatusLine());
if (resEntity != null) {
System.out.println(EntityUtils.toString(resEntity));
}
if (resEntity != null) {
resEntity.consumeContent();
}
httpclient.getConnectionManager().shutdown();
}
}
PHP 文件 upload.php
非常简单:
<?php
if (is_uploaded_file($_FILES['userfile']['tmp_name'])) {
echo "File ". $_FILES['userfile']['name'] ." uploaded successfully.\n";
move_uploaded_file ($_FILES['userfile'] ['tmp_name'], $_FILES['userfile'] ['name']);
} else {
echo "Possible file upload attack: ";
echo "filename '". $_FILES['userfile']['tmp_name'] . "'.";
print_r($_FILES);
}
?>
读取响应我得到以下结果:
executing request POST http://localhost:9002/upload.php HTTP/1.1
HTTP/1.1 200 OK Possible file upload attack: filename ''. Array ( )
所以请求成功,我能够与服务器通信,但是 PHP 没有注意到该文件 - 方法 is_uploaded_file
返回 false
并且 $_FILES
变量为空。 我不知道为什么会发生这种情况。 我已经跟踪了 HTTP 响应和请求,它们看起来没问题:
请求是:
POST /upload.php HTTP/1.1 Content-Length: 13091 Content-Type: binary/octet-stream Host: localhost:9002 Connection: Keep-Alive User-Agent: Apache-HttpClient/4.0-beta2 (java 1.5) Expect: 100-Continue ˙Ř˙ŕ..... the rest of the binary file...
响应:
HTTP/1.1 100 Continue HTTP/1.1 200 OK Date: Wed, 01 Jul 2009 06:51:57 GMT Server: Apache/2.2.8 (Win32) DAV/2 mod_ssl/2.2.8 OpenSSL/0.9.8g mod_autoindex_color PHP/5.2.5 mod_jk/1.2.26 X-Powered-By: PHP/5.2.5 Content-Length: 51 Keep-Alive: timeout=5, max=100 Connection: Keep-Alive Content-Type: text/html Possible file upload attack: filename ''.Array ( )
我正在使用 xampp 的本地 Windows XP 和远程 Linux 服务器上对此进行测试。 我还尝试使用以前版本的 HttpClient - 版本 3.1 - 结果更不清楚,is_uploaded_file
返回 false
,但是 $_FILES
数组已填充正确的数据。
I want to write Java application that will upload a file to the Apache server with PHP. The Java code uses Jakarta HttpClient library version 4.0 beta2:
import java.io.File;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.HttpVersion;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.FileEntity;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.params.CoreProtocolPNames;
import org.apache.http.util.EntityUtils;
public class PostFile {
public static void main(String[] args) throws Exception {
HttpClient httpclient = new DefaultHttpClient();
httpclient.getParams().setParameter(CoreProtocolPNames.PROTOCOL_VERSION, HttpVersion.HTTP_1_1);
HttpPost httppost = new HttpPost("http://localhost:9002/upload.php");
File file = new File("c:/TRASH/zaba_1.jpg");
FileEntity reqEntity = new FileEntity(file, "binary/octet-stream");
httppost.setEntity(reqEntity);
reqEntity.setContentType("binary/octet-stream");
System.out.println("executing request " + httppost.getRequestLine());
HttpResponse response = httpclient.execute(httppost);
HttpEntity resEntity = response.getEntity();
System.out.println(response.getStatusLine());
if (resEntity != null) {
System.out.println(EntityUtils.toString(resEntity));
}
if (resEntity != null) {
resEntity.consumeContent();
}
httpclient.getConnectionManager().shutdown();
}
}
The PHP file upload.php
is very simple:
<?php
if (is_uploaded_file($_FILES['userfile']['tmp_name'])) {
echo "File ". $_FILES['userfile']['name'] ." uploaded successfully.\n";
move_uploaded_file ($_FILES['userfile'] ['tmp_name'], $_FILES['userfile'] ['name']);
} else {
echo "Possible file upload attack: ";
echo "filename '". $_FILES['userfile']['tmp_name'] . "'.";
print_r($_FILES);
}
?>
Reading the response I get the following result:
executing request POST http://localhost:9002/upload.php HTTP/1.1
HTTP/1.1 200 OK Possible file upload attack: filename ''. Array ( )
So the request was successful, I was able to communicate with server, however PHP didn't notice the file - the method is_uploaded_file
returned false
and $_FILES
variable is empty. I have no idea why this might happend. I have tracked HTTP response and request and they look ok:
request is:
POST /upload.php HTTP/1.1 Content-Length: 13091 Content-Type: binary/octet-stream Host: localhost:9002 Connection: Keep-Alive User-Agent: Apache-HttpClient/4.0-beta2 (java 1.5) Expect: 100-Continue ˙Ř˙ŕ..... the rest of the binary file...
and response:
HTTP/1.1 100 Continue HTTP/1.1 200 OK Date: Wed, 01 Jul 2009 06:51:57 GMT Server: Apache/2.2.8 (Win32) DAV/2 mod_ssl/2.2.8 OpenSSL/0.9.8g mod_autoindex_color PHP/5.2.5 mod_jk/1.2.26 X-Powered-By: PHP/5.2.5 Content-Length: 51 Keep-Alive: timeout=5, max=100 Connection: Keep-Alive Content-Type: text/html Possible file upload attack: filename ''.Array ( )
I was testing this both on the local windows xp with xampp and remote Linux server. I have also tried to use previous version of HttpClient - version 3.1 - and the result was even more unclear, is_uploaded_file
returned false
, however $_FILES
array was filled with proper data.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(10)
我知道我迟到了,但下面是处理这个问题的正确方法,关键是使用
InputStreamBody
代替FileBody
上传多部分文件。I knew I am late to the party but below is the correct way to deal with this, the key is to use
InputStreamBody
in place ofFileBody
to upload multi-part file.如果您在本地 WAMP 上对此进行测试,您可能需要设置用于文件上传的临时文件夹。 您可以在 PHP.ini 文件中执行此操作:
您需要授予文件夹权限以允许上传 - 您需要授予的权限因操作系统而异。
If you are testing this on your local WAMP you might need to set up the temporary folder for file uploads. You can do this in your PHP.ini file:
You will need to grant permissions on the folder to allow the upload to take place - the permission you need to grant vary based on your operating system.
对于那些很难实现接受的答案(需要 org.apache.http.entity.mime.MultipartEntity)的人,您可能正在使用 org.apache.httpcomponents 4.2.*
在这种情况下,您必须显式安装 httpmime 依赖项,在我的例子中:
For those having a hard time implementing the accepted answer (which requires org.apache.http.entity.mime.MultipartEntity) you may be using org.apache.httpcomponents 4.2.*
In this case, you have to explicitly install httpmime dependency, in my case:
好吧,我使用的 Java 代码是错误的,这里是正确的 Java 类:
注意使用 MultipartEntity。
Ok, the Java code I used was wrong, here comes the right Java class:
note using MultipartEntity.
对于那些尝试使用
MultipartEntity
的人来说,更新...org.apache.http.entity.mime.MultipartEntity
在 4.3.1 中已弃用。您可以使用
MultipartEntityBuilder
创建HttpEntity
对象。对于 Maven 用户,该类可在以下依赖项中使用(与 fervisa 的答案几乎相同,只是版本更高)。
An update for those trying to use
MultipartEntity
...org.apache.http.entity.mime.MultipartEntity
is deprecated in 4.3.1.You can use
MultipartEntityBuilder
to create theHttpEntity
object.For Maven users the class is available in the following dependency (almost the same as fervisa's answer, just with a later version).
正确的方法是使用多部分 POST 方法。 请参阅 这里是客户端的示例代码。
对于 PHP,有许多可用的教程。 这是我发现的第一个。 我建议您首先使用 html 客户端测试 PHP 代码,然后尝试 java 客户端。
The correct way will be to use multipart POST method. See here for example code for the client.
For PHP there are many tutorials available. This is the first I've found. I recommend that you test the PHP code first using an html client and then try the java client.
我遇到了同样的问题,发现 httpclient 4.x 需要文件名才能与 PHP 后端一起使用。 httpclient 3.x 的情况并非如此。
所以我的解决方案是在FileBody构造函数中添加一个name参数。
ContentBody cbFile = new FileBody(文件, "image/jpeg", "FILE_NAME");
希望能帮助到你。
I ran into the same problem and found out that the file name is required for httpclient 4.x to be working with PHP backend. It was not the case for httpclient 3.x.
So my solution is to add a name parameter in the FileBody constructor.
ContentBody cbFile = new FileBody(file, "image/jpeg", "FILE_NAME");
Hope it helps.
A新版本示例在这里。
下面是原始代码的副本:
A newer version example is here.
Below is a copy of the original code:
我有一个使用 apache http 库发送图像的工作解决方案(这里非常重要的是边界添加,如果没有它在我的连接中它将无法工作):
There is my working solution for sending image with post, using apache http libraries (very important here is boundary add It won't work without it in my connection):
地方添加一个名称参数即可。
啊,您只需要在希望有帮助的
Aah you just need to add a name parameter in the
Hope it helps.