Cómo cargar un archivo usando la biblioteca Java HttpClient trabajando con PHP
Quiero escribir una aplicación Java que cargue un archivo en el servidor Apache con PHP. El código Java utiliza la biblioteca Jakarta HttpClient 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 correcto Posible ataque de carga de archivos: nombre de archivo ''. Formación ( )
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 $_FILES
la variable está vacía. No tengo idea de por qué pudo suceder esto. He seguido la respuesta y solicitud HTTP y se ven bien:
la solicitud es:
ENVIAR /upload.php HTTP/1.1 Longitud del contenido: 13091 Tipo de contenido: binario/flujo de octetos Anfitrión: localhost: 9002 Conexión: Mantener vivo Agente de usuario: Apache-HttpClient/4.0-beta2 (java 1.5) Esperar: 100-Continuar ˙Ř˙ŕ..... el resto del archivo binario...
y respuesta:
HTTP/1.1 100 Continuar HTTP/1.1 200 correcto Fecha: miércoles, 1 de julio de 2009 06:51:57 GMT Servidor: 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-Desarrollado por: PHP/5.2.5 Longitud del contenido: 51 Mantener vivo: tiempo de espera = 5, máximo = 100 Conexión: Mantener vivo Tipo de contenido: texto/html Posible ataque de carga de archivos: nombre de archivo ''.Array ( )
Estaba probando esto tanto en Windows XP local con xampp como en un 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
la matriz se llenó con los datos adecuados.
Ok, el código Java que usé era incorrecto, aquí viene la clase Java correcta:
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();
}
}
tenga en cuenta el uso de MultipartEntity.
Una actualización para aquellos que intentan usar MultipartEntity
...
org.apache.http.entity.mime.MultipartEntity
está en desuso en 4.3.1.
Puede utilizar MultipartEntityBuilder
para crear el HttpEntity
objeto.
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 igual 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>