Как загрузить файл с помощью Java HttpClient библиотека работает с PHP
Я хочу написать Java-приложение, которое будет загружать файл на сервер Apache с PHP. В коде 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 ( )
Я тестировал это как на локальном windows xp с xampp, так и на удаленном сервере Linux. Я также попытался использовать предыдущую версию HttpClient-версия 3.1 - и результат был еще более неясным,is_uploaded_file
вернулся ,$_FILES
массив был заполнен надлежащими данные.
10 ответов:
хорошо, код 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
создать
Я столкнулся с той же проблемой и узнал, что имя файла требуется для httpclient 4.x для работы с бэкэндом PHP. Это было не так для httpclient 3.x.
поэтому мое решение-добавить параметр name в конструктор 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(); } } }
Aah вам просто нужно добавить параметр name в
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()); }
Если вы тестируете это на локальном WAMP вам может потребоваться настроить временную папку для загрузки файлов. Вы можете сделать это в PHP.ini-файл:
upload_tmp_dir = "c:\mypath\mytempfolder\"
вам нужно будет предоставить разрешения на папку, чтобы разрешить загрузку - разрешение, которое вам нужно предоставить, зависит от вашей операционной системы.
для тех, кто испытывает трудности с реализацией принятого ответа (что требует организации.апаш.http.сущность.мим.MultipartEntity) вы можете использовать org.апаш.httpcomponents 4.2.* В этом случае вы должны явно установитьhttpmime зависимость, в моем случае:
<dependency> <groupId>org.apache.httpcomponents</groupId> <artifactId>httpmime</artifactId> <version>4.2.5</version> </dependency>
есть мое рабочее решение для отправки изображения с post, используя 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