not - Cómo cargar un archivo usando la biblioteca Java HttpClient trabajando con PHP
llamar archivo php desde java (10)
Aah solo necesitas agregar un parámetro de nombre en
FileBody constructor. ContentBody cbFile = new FileBody(file, "image/jpeg", "FILE_NAME");
Espero eso ayude.
Quiero escribir una aplicación Java que cargue un archivo al servidor Apache con PHP. El código de Java usa Jakarta HttpClient library versión 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();
}
}
El archivo PHP upload.php
es muy 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);
}
?>
Al leer la respuesta obtengo el siguiente resultado:
executing request POST http://localhost:9002/upload.php HTTP/1.1
HTTP/1.1 200 OK Possible file upload attack: filename ''''. Array ( )
Entonces la solicitud fue exitosa, pude comunicarme con el servidor, sin embargo, PHP no notó el archivo - el método is_uploaded_file
devolvió false
y la variable $_FILES
está vacía. No tengo idea de por qué esto podría pasar. He rastreado la respuesta y solicitud HTTP y se ven bien:
solicitud es:
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...
y respuesta:
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 ( )
Estaba probando esto tanto en el Windows XP local con xampp como en el servidor Linux remoto. También intenté usar la versión anterior de HttpClient - versión 3.1 - y el resultado fue aún menos claro, is_uploaded_file
devolvió false
, sin embargo $_FILES
array se rellenó con los datos correctos.
Ahí está mi solución de trabajo para enviar imágenes con publicaciones, usando las bibliotecas http de Apache (muy importante aquí es agregar límites. No funcionará sin ella en mi conexión):
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
Me encontré con el mismo problema y descubrí que el nombre del archivo es necesario para que httpclient 4.x funcione con PHP back-end. No fue el caso para httpclient 3.x.
Entonces mi solución es agregar un parámetro de nombre en el constructor FileBody. ContentBody cbFile = new FileBody (archivo, "image / jpeg", "FILE_NAME");
Espero eso ayude.
Ok, el código Java que utilicé estaba equivocado, aquí viene la clase correcta de 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();
}
}
nota usando MultipartEntity.
Para aquellos que tienen dificultades para implementar la respuesta aceptada (que requiere org.apache.http.entity.mime.MultipartEntity), puede estar utilizando org.apache.httpcomponents 4.2. * En este caso, debe instalar explícitamente la dependencia httpmime , en mi caso:
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpmime</artifactId>
<version>4.2.5</version>
</dependency>
Sabía que llego tarde a la fiesta, pero a continuación es la forma correcta de lidiar con esto, la clave es usar InputStreamBody
en lugar de FileBody
para cargar archivos de varias partes.
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());
}
Si está probando esto en su WAMP local, es posible que deba configurar la carpeta temporal para la carga de archivos. Puedes hacer esto en tu archivo PHP.ini:
upload_tmp_dir = "c:/mypath/mytempfolder/"
Deberá otorgar permisos en la carpeta para permitir que se realice la carga; el permiso que debe otorgar varía en función de su sistema operativo.
Una actualización para aquellos que intentan usar MultipartEntity
...
org.apache.http.entity.mime.MultipartEntity
está en desuso en 4.3.1.
Puede usar MultipartEntityBuilder
para crear el objeto HttpEntity
.
File file = new File();
HttpEntity httpEntity = MultipartEntityBuilder.create()
.addBinaryBody("file", file, ContentType.create("image/jpeg"), file.getName())
.build();
Para los usuarios de Maven, la clase está disponible en la siguiente dependencia (casi lo mismo que la respuesta de Fervisa, solo que con una versión posterior).
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpmime</artifactId>
<version>4.3.1</version>
</dependency>
Un ejemplo de versión más nueva está aquí.
A continuación hay una copia del código original:
/*
* ====================================================================
* 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();
}
}
}