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;
}
}
どのような注釈を使用する必要がありますか? @Produces({application/x-octet-stream})
を使用して@GET
を推奨する人がいますが、それは正しい方法ですか?送信するファイルは特定のものであるため、クライアントはファイルを参照する必要がありません。誰も私がファイルを送信する方法を教えてくれますか? base64を使用してJSONオブジェクトとして送信するためにエンコードする必要がありますか?または、JSONオブジェクトとして送信するためにエンコードは必要ありませんか?あなたが与えるかもしれない助けをありがとう。
Base64でバイナリデータをエンコードしてJSONでラップすることはお勧めしません。応答のサイズが不必要に増加し、処理が遅くなります。
application/octect-stream
(JAX-RS APIの一部であるため、Jerseyにロックされていない)のファクトリメソッドの1つを使用して、GETおよびjavax.ws.rs.core.Response
を使用してファイルデータを提供するだけです。
@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
オブジェクトがない場合は、 Response.ok(entity, mediaType)
もそれを処理できるはずです。
ダウンロードするファイルを返したい場合、特にファイルアップロード/ダウンロードの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>