как правильно отправить файл из веб-службы REST клиенту?
Я только начал разрабатывать службы REST, но столкнулся с трудной ситуацией: отправка файлов из моей службы REST моему клиенту. До сих пор я получил представление о том, как отправлять простые типы данных (строки, целые числа и т. д.), Но отправка файла-это другое дело, поскольку существует так много форматов файлов, что я даже не знаю, где я должен начать. Моя служба REST сделана на Java, и я использую Джерси, я отправляю все данные, используя формат JSON.
Я читал о кодировка base64, некоторые люди говорят, что это хорошая техника, другие говорят, что это не из-за проблем с размером файла. Каков правильный путь? Вот как выглядит простой класс ресурсов в моем проекте:
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;
}
}
Я предполагаю, что код для отправки файла будет что-то вроде:
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;
}
}
какие аннотации я должен использовать? Я видел, что некоторые люди рекомендуют для @GET
используя @Produces({application/x-octet-stream})
, это правильно? Файлы, которые я отправляю, являются конкретными, поэтому клиент не нужно просматривать файлы. Может ли кто-нибудь помочь мне в том, как я должен отправить файл? Должен ли я кодировать его с помощью base64, чтобы отправить его как объект JSON? или кодировка не нужна, чтобы отправить его как объект JSON? Спасибо за любую помощь вы можете дать.
4 ответа:
Я не рекомендую кодировать двоичные данные в base64 и обертывать их в JSON. Это просто без необходимости увеличит размер ответа и замедлит работу.
просто подавайте данные файла с помощью GET и
application/octect-stream
используя один из методов фабрикиjavax.ws.rs.core.Response
(часть API JAX-RS, так что вы не заперты в Джерси):@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(); }
если у вас нет фактического
Если вы хотите вернуть файл для загрузки, особенно если вы хотите интегрироваться с некоторыми библиотеками JavaScript для загрузки файлов, то код ниже должен выполнить задание:
@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(); }
измените адрес машины с localhost на IP-адрес, с которым вы хотите, чтобы ваш клиент подключался к вызову указанной ниже службы.
клиент для вызова REST webservice:
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(); } }
обслуживание к клиенту ответа:
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 требуется:
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>