REST 웹 서비스에서 클라이언트로 파일을 보내는 올바른 방법은 무엇입니까?
REST 서비스를 개발하기 시작한 지 얼마 되지 않았는데 REST 서비스에서 고객에게 파일을 보내는 어려운 상황에 직면했습니다.지금까지 간단한 데이터 타입(스트링, 정수 등)을 송신하는 방법은 익히 알고 있습니다만, 파일 포맷이 너무 많아서 어디서부터 시작해야 할지 알 수 없기 때문에 파일을 송신하는 것은 다른 문제입니다.나의 REST 서비스는 Java에서 만들어졌고 나는 Jersey를 사용하고 있고, 나는 모든 데이터를 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})
, 그것이 올바른 방법입니까?보내는 파일은 특정 파일이기 때문에 클라이언트가 파일을 검색할 필요가 없습니다.파일을 어떻게 보내야 하는지 누가 좀 가르쳐 주시겠어요?JSON 오브젝트로 전송하려면 base64를 사용하여 인코딩해야 합니까?아니면 JSON 오브젝트로 전송하기 위해 인코딩이 필요하지 않은가?도와주셔서 감사합니다.
base64에서 바이너리 데이터를 인코딩하여 JSON으로 래핑하는 것은 권장하지 않습니다.그것은 불필요하게 반응의 크기를 늘리고 상황을 느리게 만들 것이다.
GET을 사용하여 파일 데이터를 간단하게 처리하여application/octect-stream
공장 출하 시 방법 중 하나를 사용합니다(JAX-RS API의 일부이므로 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();
}
만약 당신이 실제를 가지고 있지 않다면File
반대하지만, 하지만InputStream
에서는, 그것도 처리할 수 있을 것입니다.
다운로드할 파일을 반환하고 싶은 경우, 특히 파일 업로드/다운로드의 javascript libs와 통합하고 싶은 경우 아래 코드가 작업을 수행합니다.
@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 웹 서비스를 호출하는 클라이언트:
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>
JSON을 사용하고 있기 때문에, 회선을 개입시켜 송신하기 전에, Base64 Encode를 사용합니다.
파일이 큰 경우는, BSON 또는 바이너리 전송에 적합한 다른 형식을 참조해 주세요.
압축이 잘 되면 base64로 인코딩하기 전에 파일을 압축할 수도 있습니다.
언급URL : https://stackoverflow.com/questions/12239868/whats-the-correct-way-to-send-a-file-from-rest-web-service-to-client
'source' 카테고리의 다른 글
두 숫자를 더하면 합계가 계산되지 않고 두 숫자를 연결할 수 있습니다. (0) | 2022.12.08 |
---|---|
SQL Select 문의 동적 열, "정의되지 않은" 값 유지 (0) | 2022.12.08 |
다운로드 RDS 스냅샷 (0) | 2022.11.28 |
Java에서 null을 사용할 수 있는 이유는 무엇입니까? (0) | 2022.11.28 |
루프를 위해 vuejs의 첫 번째 요소에 class="active"를 설정하는 방법 (0) | 2022.11.28 |