java - servicios - qué es una api rest y para qué sirve
¿Cuál es la forma correcta de enviar un archivo desde el servicio web REST al cliente? (5)
Cambie la dirección de la máquina de localhost a la dirección IP con la que desea que se conecte su cliente para llamar al servicio mencionado más abajo.
Cliente para llamar al servicio web REST:
package in.india.client.downloadfiledemo;
import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response.Status;
import com.sun.jersey.api.client.Client;
import com.sun.jersey.api.client.ClientHandlerException;
import com.sun.jersey.api.client.ClientResponse;
import com.sun.jersey.api.client.UniformInterfaceException;
import com.sun.jersey.api.client.WebResource;
import com.sun.jersey.multipart.BodyPart;
import com.sun.jersey.multipart.MultiPart;
public class DownloadFileClient {
private static final String BASE_URI = "http://localhost:8080/DownloadFileDemo/services/downloadfile";
public DownloadFileClient() {
try {
Client client = Client.create();
WebResource objWebResource = client.resource(BASE_URI);
ClientResponse response = objWebResource.path("/")
.type(MediaType.TEXT_HTML).get(ClientResponse.class);
System.out.println("response : " + response);
if (response.getStatus() == Status.OK.getStatusCode()
&& response.hasEntity()) {
MultiPart objMultiPart = response.getEntity(MultiPart.class);
java.util.List<BodyPart> listBodyPart = objMultiPart
.getBodyParts();
BodyPart filenameBodyPart = listBodyPart.get(0);
BodyPart fileLengthBodyPart = listBodyPart.get(1);
BodyPart fileBodyPart = listBodyPart.get(2);
String filename = filenameBodyPart.getEntityAs(String.class);
String fileLength = fileLengthBodyPart
.getEntityAs(String.class);
File streamedFile = fileBodyPart.getEntityAs(File.class);
BufferedInputStream objBufferedInputStream = new BufferedInputStream(
new FileInputStream(streamedFile));
byte[] bytes = new byte[objBufferedInputStream.available()];
objBufferedInputStream.read(bytes);
String outFileName = "D:/"
+ filename;
System.out.println("File name is : " + filename
+ " and length is : " + fileLength);
FileOutputStream objFileOutputStream = new FileOutputStream(
outFileName);
objFileOutputStream.write(bytes);
objFileOutputStream.close();
objBufferedInputStream.close();
File receivedFile = new File(outFileName);
System.out.print("Is the file size is same? :/t");
System.out.println(Long.parseLong(fileLength) == receivedFile
.length());
}
} catch (UniformInterfaceException e) {
e.printStackTrace();
} catch (ClientHandlerException e) {
e.printStackTrace();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
public static void main(String... args) {
new DownloadFileClient();
}
}
Servicio al cliente de respuesta:
package in.india.service.downloadfiledemo;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import com.sun.jersey.multipart.MultiPart;
@Path("downloadfile")
@Produces("multipart/mixed")
public class DownloadFileResource {
@GET
public Response getFile() {
java.io.File objFile = new java.io.File(
"D:/DanGilbert_2004-480p-en.mp4");
MultiPart objMultiPart = new MultiPart();
objMultiPart.type(new MediaType("multipart", "mixed"));
objMultiPart
.bodyPart(objFile.getName(), new MediaType("text", "plain"));
objMultiPart.bodyPart("" + objFile.length(), new MediaType("text",
"plain"));
objMultiPart.bodyPart(objFile, new MediaType("multipart", "mixed"));
return Response.ok(objMultiPart).build();
}
}
JAR necesitaba:
jersey-bundle-1.14.jar
jersey-multipart-1.14.jar
mimepull.jar
WEB.XML:
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
id="WebApp_ID" version="2.5">
<display-name>DownloadFileDemo</display-name>
<servlet>
<display-name>JAX-RS REST Servlet</display-name>
<servlet-name>JAX-RS REST Servlet</servlet-name>
<servlet-class>com.sun.jersey.spi.container.servlet.ServletContainer</servlet-class>
<init-param>
<param-name>com.sun.jersey.config.property.packages</param-name>
<param-value>in.india.service.downloadfiledemo</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>JAX-RS REST Servlet</servlet-name>
<url-pattern>/services/*</url-pattern>
</servlet-mapping>
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
</web-app>
Empecé a desarrollar servicios REST, pero me encontré con una situación difícil: enviar archivos de mi servicio REST a mi cliente. Hasta ahora me he acostumbrado a cómo enviar tipos de datos simples (cadenas, enteros, etc.), pero enviar un archivo es una cuestión diferente ya que hay tantos formatos de archivo que no sé por dónde debería comenzar. Mi servicio REST está hecho en Java y estoy usando Jersey, estoy enviando todos los datos usando el formato JSON.
He leído sobre la codificación de base64, algunas personas dicen que es una buena técnica, otros dicen que no se debe a problemas de tamaño de archivo. ¿Cuál es la manera correcta? Así es como está buscando una clase de recursos simple en mi proyecto:
import java.sql.SQLException;
import java.util.List;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Request;
import javax.ws.rs.core.UriInfo;
import com.mx.ipn.escom.testerRest.dao.TemaDao;
import com.mx.ipn.escom.testerRest.modelo.Tema;
@Path("/temas")
public class TemaResource {
@GET
@Produces({MediaType.APPLICATION_JSON})
public List<Tema> getTemas() throws SQLException{
TemaDao temaDao = new TemaDao();
List<Tema> temas=temaDao.getTemas();
temaDao.terminarSesion();
return temas;
}
}
Supongo que el código para enviar un archivo sería algo así como:
import java.sql.SQLException;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
@Path("/resourceFiles")
public class FileResource {
@GET
@Produces({application/x-octet-stream})
public File getFiles() throws SQLException{ //I''m not really sure what kind of data type I should return
// Code for encoding the file or just send it in a data stream, I really don''t know what should be done here
return file;
}
}
¿Qué tipo de anotaciones debería usar? He visto a algunas personas recomendar un @GET
usando @Produces({application/x-octet-stream})
, ¿es esa la forma correcta? Los archivos que estoy enviando son específicos, por lo que el cliente no necesita navegar por los archivos. ¿Alguien puede guiarme en cómo se supone que debo enviar el archivo? ¿Debería codificarlo usando base64 para enviarlo como un objeto JSON? o la codificación no es necesaria para enviarlo como un objeto JSON? Gracias por cualquier ayuda que pueda dar.
Como estás usando JSON, me gustaría codificarlo Base64 antes de enviarlo a través del cable.
Si los archivos son grandes, intente ver BSON o algún otro formato que sea mejor con transferencias binarias.
También puede comprimir los archivos, si se comprimen bien, antes de que base64 los codifique.
No recomiendo codificar datos binarios en base64 y envolverlos en JSON. Simplemente aumentará innecesariamente el tamaño de la respuesta y disminuirá la velocidad.
Simplemente application/octect-stream
sus datos de archivo usando GET y application/octect-stream
usando uno de los métodos de fábrica de javax.ws.rs.core.Response
(parte de JAX-RS API, para que no esté bloqueado en Jersey):
@GET
@Produces(MediaType.APPLICATION_OCTET_STREAM)
public Response getFile() {
File file = ... // Initialize this to the File path you want to serve.
return Response.ok(file, MediaType.APPLICATION_OCTET_STREAM)
.header("Content-Disposition", "attachment; filename=/"" + file.getName() + "/"" ) //optional
.build();
}
Si no tiene un objeto File
real, sino un InputStream
, Response.ok(entity, mediaType)
debería poder manejarlo.
Si desea devolver un archivo para descargar, especialmente si desea integrarlo con algunas librerías javascript de carga / descarga de archivos, entonces el siguiente código debe hacer el trabajo:
@GET
@Path("/{key}")
public Response download(@PathParam("key") String key,
@Context HttpServletResponse response) throws IOException {
try {
//Get your File or Object from wherever you want...
//you can use the key parameter to indentify your file
//otherwise it can be removed
//let''s say your file is called "object"
response.setContentLength((int) object.getContentLength());
response.setHeader("Content-Disposition", "attachment; filename="
+ object.getName());
ServletOutputStream outStream = response.getOutputStream();
byte[] bbuf = new byte[(int) object.getContentLength() + 1024];
DataInputStream in = new DataInputStream(
object.getDataInputStream());
int length = 0;
while ((in != null) && ((length = in.read(bbuf)) != -1)) {
outStream.write(bbuf, 0, length);
}
in.close();
outStream.flush();
} catch (S3ServiceException e) {
e.printStackTrace();
} catch (ServiceException e) {
e.printStackTrace();
}
return Response.ok().build();
}
package com.mastercard.dispute.pro.openapi.casefiling.restservice.impl;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import javax.ws.rs.core.MediaType;
public class DownloadFileClient {
// http://localhost:8080/RESTfulExample/json/product/get
public static void main(String[] args) {
FileOutputStream out = null;
try {
URL url = new URL(
"http://localhost:8080/ProService/json/claims/document/case/10000016?userId=n000027&&format=ORIGINAL");
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setRequestMethod("GET");
conn.setRequestProperty("Accept", MediaType.MULTIPART_FORM_DATA);
conn.setRequestProperty("system_id", "op");
conn.setRequestProperty("source", "s0001");
conn.setRequestProperty("user_id", "n000027");
if (conn.getResponseCode() != 200) {
throw new RuntimeException("Failed : HTTP error code : "
+ conn.getResponseCode());
}
/*
* BufferedReader br = new BufferedReader(new InputStreamReader(
* (conn.getInputStream())));
*/
InputStream in = conn.getInputStream();
out = new FileOutputStream(
"C://Users//E077106//Desktop//upload_15_05_2017//sunil.zip");
copy(in, out, 1024);
out.close();
String output;
System.out.println("Output from Server .... /n");
/*
* while ((output = br.readLine()) != null) {
* System.out.println(output); }
*/
conn.disconnect();
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
public static void copy(InputStream input, OutputStream output,
int bufferSize) throws IOException {
byte[] buf = new byte[bufferSize];
int n = input.read(buf);
while (n >= 0) {
output.write(buf, 0, n);
n = input.read(buf);
}
output.flush();
}
}