Sube imágenes a Imgur con Apache HttpComponents

Quizá se te haya planteado la necesidad de almacenar imágenes en un proveedor externo dentro de tu aplicación Java, para esto subirlo a Imgur es una muy buena solución, ya que tiene un API Rest de lo más completo y bastante sencillo de utilizar.

Desde su API puedes tener las mismas operaciones que puedes realizar desde su web, pero en esta ocasión nos centraremos únicamente en una, subir una imagen.

Lo primero que tienes que hacer (si no tienes un usuario) es registrarte en su web rellenando un sencillo formulario.

Ya tenemos un usuario para entrar en imgur, pero esto no es suficiente para utilizar su API, debemos conseguir un Client ID, para ello debemos registrar una aplicación.

Lo mínimo que debemos rellenar es el nombre de la aplicación, marcar la segunda opción de «Authorization type: OAuth 2 authorization without a callback URL» y escribir un Email. Una vez hecho click en submit nos proporcionará un client_id y un client_secret, para subir imágenes solo necesitamos el primero, el client_id.

Con todo esto ya tenemos lo suficiente para ir a Java y preparar nuestra aplicación para subir imágenes.

Las librerías que nos van a facilitar mucho el trabajo son dos, HttpComponents de Apache (para preparar un cliente y hacer la llamada a su API Rest) y Jackson de Fasterxml.com para convertir el JSON que nos responde el API en un bean de Java, para ello añadimos sus dependencias en el pom.xml de Maven.

                <dependency>
			<groupId>org.apache.httpcomponents</groupId>
			<artifactId>httpclient</artifactId>
			<version>4.5.10</version>
		</dependency>
		<dependency>
			<groupId>com.fasterxml.jackson.core</groupId>
			<artifactId>jackson-databind</artifactId>
			<version>2.9.8</version>
		</dependency>

Vamos al código, lo primero que debemos hacer es declarar el cliente de tipo HttpClients.

CloseableHttpClient client = HttpClients.custom().setSSLHostnameVerifier(NoopHostnameVerifier.INSTANCE).build();

Es importante el detalle de añadir setSSLHostnameVerifier(NoopHostnameVerifier.INSTANCE) para evitar problemas de certificado SSL ya que estamos ante una conexión https (en concreto a «https://api.imgur.com/3/upload«).

Vamos a hacer una llamada POST y además usaremos como seguridad el client_id que nos proporcionaron al registrar la aplicación, así que declararemos un HttpPost y le añadiremos como cabecera la autorización por «Client-ID» con el client_id.

String address = "https://api.imgur.com/3/upload";
HttpPost post = new HttpPost(address);
post.addHeader("Authorization", "Client-ID " + clientID);

Como vamos a subir una imágen que está en nuestro servidor, es necesario leer el fichero (con File), y para poder enviarlo como un String en Base64, primero lo convertimos a array de bytes y después ya a Base64.

BufferedImage image = null;
File file = new File(imageDir);
image = ImageIO.read(file);
ByteArrayOutputStream byteArray = new ByteArrayOutputStream();
ImageIO.write(image, "png", byteArray);
byte[] byteImage = byteArray.toByteArray();
String dataImage = new Base64().encodeAsString(byteImage);

Ya tenemos nuestra ristra de caracteres en String para enviar al servidor en dataImage, así que nos aprovechamos de NameValuePair para asociar el nombre «image» con nuestro dataImage.

List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>(1);
nameValuePairs.add(new BasicNameValuePair("image", dataImage));

Ya solo nos queda añadir alHttpPost nuestra pareja «image:dataImage» como un objeto de tipo UrlEncodedFormEntity y ejecutar el post contra el API y recuperar el JSON que nos responde convirtiéndolo a String con EntityUtils.

post.setEntity(new UrlEncodedFormEntity(nameValuePairs));
HttpResponse response = client.execute(post);
String jsonString = EntityUtils.toString(response.getEntity());

Y con esto ya hemos terminado la parte del cliente, la imagen ya se habrá subido al servidor y toda la información al respecto la tendremos en el String jsonString.

Ahora nos queda parsear el String de la respuesta para convertirlo en un bean de Java mucho más manejable, para ello llega el turno de Jackson.

Lo primero que debemos hacer es ver el String que nos llega y el aspecto que tiene el JSON, veremos que tiene un aspecto parecido a este:

{
  "data": {
    "id": "orunSTu",
    "title": null,
    "description": null,
    "datetime": 1495556889,
    "type": "image/gif",
    "animated": false,
    "width": 1,
    "height": 1,
    "size": 42,
    "views": 0,
    "bandwidth": 0,
    "vote": null,
    "favorite": false,
    "nsfw": null,
    "section": null,
    "account_url": null,
    "account_id": 0,
    "is_ad": false,
    "in_most_viral": false,
    "tags": [],
    "ad_type": 0,
    "ad_url": "",
    "in_gallery": false,
    "deletehash": "x70po4w7BVvSUzZ",
    "name": "",
    "link": "http://i.imgur.com/orunSTu.gif"
  },
  "success": true,
  "status": 200
}

Esto es un objecto «data» con un montón de campos, para que Jackson haga su magia debemos picar un bean con exactamente lo mismo. No te preocupes, ya te he ahorrado el trabajo.

public class Data {
	private String id;
	private String title;
	private String description;
	private String datetime;
	private String type;
	private boolean animated;
	private int width;
	private int height;
	private int size;
	private int views;
	private int bandwidth;
	private int vote;
	private boolean favorite;
	private String nsfw;
	private String section;
	private String account_url;
	private int account_id;
	private boolean is_ad;
	private boolean in_most_viral;
	private boolean has_sound;
	private String[] tags;
	private int ad_type;
	private String ad_url;
	private String edited;
	private boolean in_gallery;
	private String deletehash;
	private String name;
	private String link;

// A partir de aquí, los get y set correspondientes.
}

Habrá que meter este objecto dentro de un bean para cumplir exactactamente con el JSON que recibimos y ya estamos listos para convertir ese String en un bean repleto de datos y en solo una línea.

ImgUrResponse responseJson = new ObjectMapper().readValue(jsonString, ImgUrResponse.class);

ImgUrResponse es un objeto que hace referencia al objeto Data que hemos creado con todos los campos del JSON, ya podemos manejar la información de la respuesta cómodamente, por ejemplo si queremos conocer la url en donde se encuentra la imagen que se ha subido es solo cuestión de hacer.

responseJson.getData().getLink();

Como puedes ver es bastantes encillo el poder realizar una pequeña aplicación para subir imágenes a Imgur, como siempre os he dejado todo el código fuente en GitHub para su uso y disfrute.

Dejar una contestacion

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *