如何使用Java HttpClient库使用PHP上传文件
我想编写Java应用程序,它将使用PHP将file upload到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 可能的file upload攻击:文件名''。 排列 ( )
所以请求是成功的,我能够与服务器通信,但PHP没有注意到文件 – 方法is_uploaded_file
返回false
和$_FILES
variables是空的。 我不知道为什么会发生这种情况。 我已经跟踪HTTP响应和请求,他们看起来不错:
要求是:
POST /upload.php HTTP / 1.1 内容长度:13091 内容types:二进制/八位字节stream 主机:localhost:9002 连接:保持活跃 User-Agent:Apache-HttpClient / 4.0-beta2(java 1.5) 期待:100-继续 ˙Ř˙ŕ.....二进制文件的其余部分...
和回应:
HTTP / 1.1 100继续 HTTP / 1.1 200 OK date:Wed,01 Jul 2009 06:51:57 GMT 服务器: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 内容长度:51 保持活跃:超时= 5,最大= 100 连接:保持活跃 内容types:文本/ HTML 可能的file upload攻击:文件名''.Array ( )
我正在用xampp和远程Linux服务器在本地windows xp上testing这个。 我也尝试使用以前版本的HttpClient – 版本3.1 – 结果是更加不清楚, is_uploaded_file
返回false
,但$_FILES
数组充满了正确的数据。
好的,我使用的Java代码是错误的,来自正确的Java类:
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.mime.MultipartEntity; import org.apache.http.entity.mime.content.ContentBody; import org.apache.http.entity.mime.content.FileBody; 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:9001/upload.php"); File file = new File("c:/TRASH/zaba_1.jpg"); MultipartEntity mpEntity = new MultipartEntity(); ContentBody cbFile = new FileBody(file, "image/jpeg"); mpEntity.addPart("userfile", cbFile); httppost.setEntity(mpEntity); 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(); } }
请注意使用MultipartEntity。
那些试图使用MultipartEntity
的更新…
org.apache.http.entity.mime.MultipartEntity
在4.3.1中被弃用。
您可以使用MultipartEntityBuilder
创buildHttpEntity
对象。
File file = new File(); HttpEntity httpEntity = MultipartEntityBuilder.create() .addBinaryBody("file", file, ContentType.create("image/jpeg"), file.getName()) .build();
对于Maven用户来说,这个类在下面的依赖关系中是可用的(几乎和fervisa的答案一样,只是后面的版本)。
<dependency> <groupId>org.apache.httpcomponents</groupId> <artifactId>httpmime</artifactId> <version>4.3.1</version> </dependency>
正确的方法是使用多部分POST方法。 请参阅此处的客户端示例代码。
对于PHP有许多教程可用。 这是我find的第一个 。 我build议你首先使用html客户端testingPHP代码,然后尝试java客户端。
我遇到了同样的问题,发现httpclient 4.x需要文件名才能使用PHP后端。 httpclient 3.x并不是这种情况。
所以我的解决scheme是在FileBody构造函数中添加一个名称参数。 ContentBody cbFile = new FileBody(file,“image / jpeg”,“FILE_NAME”);
希望它有帮助。
更新版本的例子在这里。
以下是原始代码的副本:
/* * ==================================================================== * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * ==================================================================== * * This software consists of voluntary contributions made by many * individuals on behalf of the Apache Software Foundation. For more * information on the Apache Software Foundation, please see * <http://www.apache.org/>. * */ package org.apache.http.examples.entity.mime; import java.io.File; import org.apache.http.HttpEntity; import org.apache.http.client.methods.CloseableHttpResponse; import org.apache.http.client.methods.HttpPost; import org.apache.http.entity.ContentType; import org.apache.http.entity.mime.MultipartEntityBuilder; import org.apache.http.entity.mime.content.FileBody; import org.apache.http.entity.mime.content.StringBody; import org.apache.http.impl.client.CloseableHttpClient; import org.apache.http.impl.client.HttpClients; import org.apache.http.util.EntityUtils; /** * Example how to use multipart/form encoded POST request. */ public class ClientMultipartFormPost { public static void main(String[] args) throws Exception { if (args.length != 1) { System.out.println("File path not given"); System.exit(1); } CloseableHttpClient httpclient = HttpClients.createDefault(); try { HttpPost httppost = new HttpPost("http://localhost:8080" + "/servlets-examples/servlet/RequestInfoExample"); FileBody bin = new FileBody(new File(args[0])); StringBody comment = new StringBody("A binary file of some kind", ContentType.TEXT_PLAIN); HttpEntity reqEntity = MultipartEntityBuilder.create() .addPart("bin", bin) .addPart("comment", comment) .build(); httppost.setEntity(reqEntity); System.out.println("executing request " + httppost.getRequestLine()); CloseableHttpResponse response = httpclient.execute(httppost); try { System.out.println("----------------------------------------"); System.out.println(response.getStatusLine()); HttpEntity resEntity = response.getEntity(); if (resEntity != null) { System.out.println("Response content length: " + resEntity.getContentLength()); } EntityUtils.consume(resEntity); } finally { response.close(); } } finally { httpclient.close(); } } }
啊,你只需要在中添加一个名称参数
FileBody constructor. ContentBody cbFile = new FileBody(file, "image/jpeg", "FILE_NAME");
希望它有帮助。
我知道我晚了,但下面是处理这个问题的正确方法,关键是使用InputStreamBody
代替FileBody
上传多部分文件。
try { HttpClient httpclient = new DefaultHttpClient(); HttpPost postRequest = new HttpPost("https://someserver.com/api/path/"); postRequest.addHeader("Authorization",authHeader); //don't set the content type here //postRequest.addHeader("Content-Type","multipart/form-data"); MultipartEntity reqEntity = new MultipartEntity(HttpMultipartMode.BROWSER_COMPATIBLE); File file = new File(filePath); FileInputStream fileInputStream = new FileInputStream(file); reqEntity.addPart("parm-name", new InputStreamBody(fileInputStream,"image/jpeg","file_name.jpg")); postRequest.setEntity(reqEntity); HttpResponse response = httpclient.execute(postRequest); }catch(Exception e) { Log.e("URISyntaxException", e.toString()); }
如果你正在testing你的本地WAMP,你可能需要设置file upload的临时文件夹。 你可以在你的PHP.ini文件中做到这一点:
upload_tmp_dir = "c:\mypath\mytempfolder\"
您需要授予该文件夹的权限以允许上传 – 您需要授予的权限因您的操作系统而异。
对于那些很难实现接受的答案(这需要org.apache.http.entity.mime.MultipartEntity),你可能会使用org.apache.httpcomponents 4.2。*在这种情况下,你必须明确地安装 httpmime依赖,在我的情况:
<dependency> <groupId>org.apache.httpcomponents</groupId> <artifactId>httpmime</artifactId> <version>4.2.5</version> </dependency>
有我的工作解决scheme发送图像后,使用Apache HTTP库(这里非常重要的边界添加它不会没有它在我的连接):
ByteArrayOutputStream baos = new ByteArrayOutputStream(); bitmap.compress(Bitmap.CompressFormat.PNG, 100, baos); byte[] imageBytes = baos.toByteArray(); HttpClient httpclient = new DefaultHttpClient(); HttpPost httpPost = new HttpPost(StaticData.AMBAJE_SERVER_URL + StaticData.AMBAJE_ADD_AMBAJ_TO_GROUP); String boundary = "-------------" + System.currentTimeMillis(); httpPost.setHeader("Content-type", "multipart/form-data; boundary="+boundary); ByteArrayBody bab = new ByteArrayBody(imageBytes, "pic.png"); StringBody sbOwner = new StringBody(StaticData.loggedUserId, ContentType.TEXT_PLAIN); StringBody sbGroup = new StringBody("group", ContentType.TEXT_PLAIN); HttpEntity entity = MultipartEntityBuilder.create() .setMode(HttpMultipartMode.BROWSER_COMPATIBLE) .setBoundary(boundary) .addPart("group", sbGroup) .addPart("owner", sbOwner) .addPart("image", bab) .build(); httpPost.setEntity(entity); try { HttpResponse response = httpclient.execute(httpPost); ...then reading response
- 为什么使用HttpClient进行同步连接?
- Android弃用apache模块(HttpClient,HttpResponse等)
- 调用Web API时,C#不受支持的授权types
- 我需要Android中的HttpClient的替代选项来将数据发送到PHP,因为它不再受支持
- DefaultHttpClient到AndroidHttpClient
- 在Android中使用HttpClient和HttpPost和post参数
- 如何将json添加到java中的一个http文章的正文
- org.apache.http.entity.FileEntity在Android 6(棉花糖)
- Android:如何获取HttpClient请求的状态码