RestEasyを使ってjson経由でバイナリファイルをやり取りする
RestEasyの返すjsonにBase64エンコーディングした文字列でバイナリを埋め込む。
それをクライアントが受信してデコードしてファイルに戻すサンプル。
#xml経由にしたければ @Produces("application/xml") にする。
pom.xml
<?xml version="1.0" encoding="UTF-16"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>sample</groupId> <artifactId>sample</artifactId> <packaging>war</packaging> <version>0.0.1-SNAPSHOT</version> <!-- TODO project name --> <name>quickstart</name> <description/> <dependencies> <dependency> <groupId>commons-httpclient</groupId> <artifactId>commons-httpclient</artifactId> <version>3.1</version> </dependency> <dependency> <groupId>org.jboss.resteasy</groupId> <artifactId>resteasy-jaxrs</artifactId> <version>2.0.1.GA</version> <!-- filter out unwanted jars --> <exclusions> <exclusion> <groupId>javax.servlet</groupId> <artifactId>servlet-api</artifactId> </exclusion> <exclusion> <groupId>javax.xml.bind</groupId> <artifactId>jaxb-api</artifactId> </exclusion> <exclusion> <groupId>com.sun.xml.bind</groupId> <artifactId>jaxb-impl</artifactId> </exclusion> </exclusions> </dependency> <dependency> <groupId>org.jboss.resteasy</groupId> <artifactId>resteasy-jettison-provider</artifactId> <version>2.0.1.GA</version> <exclusions> <exclusion> <groupId>javax.xml.bind</groupId> <artifactId>jaxb-api</artifactId> </exclusion> <exclusion> <groupId>com.sun.xml.bind</groupId> <artifactId>jaxb-impl</artifactId> </exclusion> <exclusion> <groupId>javax.xml.stream</groupId> <artifactId>stax-api</artifactId> </exclusion> </exclusions> </dependency> </dependencies> <repositories> <repository> <id>jboss</id> <name>jboss repo</name> <url>http://repository.jboss.org/nexus/content/groups/public/</url> </repository> </repositories> <build> <resources> <resource> <filtering>false</filtering> <directory>src/main/resources</directory> </resource> <resource> <filtering>false</filtering> <directory>src/main/java</directory> <includes> <include>**</include> </includes> <excludes> <exclude>**/*.java</exclude> </excludes> </resource> </resources> <testResources> <testResource> <filtering>false</filtering> <directory>src/test/java</directory> <includes> <include>**</include> </includes> <excludes> <exclude>**/*.java</exclude> </excludes> </testResource> </testResources> <plugins> <plugin> <inherited>true</inherited> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <configuration> <source>1.6</source> <target>1.6</target> <optimize>true</optimize> <debug>true</debug> </configuration> </plugin> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-eclipse-plugin</artifactId> <configuration> <downloadSources>true</downloadSources> </configuration> </plugin> </plugins> </build> </project>
web.xml
<?xml version="1.0" encoding="ISO-8859-1"?> <web-app xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd" version="2.4"> <display-name>sample</display-name> <context-param> <param-name>resteasy.scan</param-name> <param-value>true</param-value> </context-param> <listener> <listener-class>org.jboss.resteasy.plugins.server.servlet.ResteasyBootstrap</listener-class> </listener> <servlet> <servlet-name>Resteasy</servlet-name> <servlet-class>org.jboss.resteasy.plugins.server.servlet.HttpServletDispatcher</servlet-class> <load-on-startup>2</load-on-startup> </servlet> <servlet-mapping> <servlet-name>Resteasy</servlet-name> <url-pattern>/*</url-pattern> </servlet-mapping> </web-app>
サーバ側
package sample.sample.resources; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import javax.ws.rs.GET; import javax.ws.rs.Path; import javax.ws.rs.Produces; import javax.ws.rs.QueryParam; import javax.ws.rs.core.Response; import javax.ws.rs.core.Response.ResponseBuilder; import org.apache.commons.codec.binary.Base64; import sample.sample.bean.ResponseBean; /** * ローカルのファイルをJSONで処理する * * @author bose999 * */ @Path("/sampleBinrary") public class SampleBinaryResource { /** * コンストラクタ */ public SampleBinaryResource() { } /** * GETメソッドのQueryParamのfileNameをローカルのファイルシステムから取得し * Base64エンコード文字列としてjsonで返す * * @param fileName * @return Response */ @GET @Produces("application/json") public Response getSample(@QueryParam("fileName") String fileName) { String fileBinaryString = ""; try { // fileをbyte[]で取得する byte[] fileBinary = readBinaryFile("/data/sampleBinary/" + fileName); // byte[]をBase64エンコーディングしてUTF-8文字列にする byte[] encoded = Base64.encodeBase64(fileBinary); fileBinaryString = new String(encoded, "UTF-8"); } catch (IOException e) { return makeResponse(404, null); } // RestEasyにステータスコード200でResponseBeanの内容でXMLを生成して処理を返してもらう return makeResponse(200, fileBinaryString); } /** * statusCodeとreturnStringの内容でレスポンスのXMLを生成する * * @param statusCode * int * @param returnString * String * @return Response */ private Response makeResponse(int statusCode, String returnString) { ResponseBean responseBean = new ResponseBean(); responseBean.returnString = returnString; ResponseBuilder responseBuilder = Response.status(statusCode); if (returnString == null) { // 返す文字列がnullなので空文字をセット responseBuilder = responseBuilder.entity(""); } else { // jsonを返す為にResponseBeanを渡す responseBuilder = responseBuilder.entity(responseBean); } // Responseを生成する Response response = responseBuilder.build(); return response; } /** * フルパスのファイル名のファイルをbyte[]に変換する * * @param fileName * String * @return byte[] * @throws IOException */ private static byte[] readBinaryFile(String fileName) throws IOException { File file = new File(fileName); int fileLength = (int) file.length(); byte[] bytes = new byte[fileLength]; InputStream inputStream = null; try { inputStream = new FileInputStream(file); inputStream.read(bytes); } finally { if (inputStream != null) { inputStream.close(); } } return bytes; } }
サーバ側Bean
package sample.sample.bean; import javax.xml.bind.annotation.XmlElement; import javax.xml.bind.annotation.XmlRootElement; @XmlRootElement(name="response") public class ResponseBean { @XmlElement(name="file") public String returnString; }
クライアント
package sample.sample.bean.client; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.OutputStream; import java.io.UnsupportedEncodingException; import javax.ws.rs.core.UriBuilder; import org.apache.commons.codec.binary.Base64; import org.jboss.resteasy.client.ClientRequest; import org.jboss.resteasy.client.ClientResponse; import org.jboss.resteasy.plugins.providers.RegisterBuiltin; import org.jboss.resteasy.spi.ResteasyProviderFactory; import sample.sample.bean.ResponseBean; /** * http://localhost:8080/sample/sampleBinary/xxxに * アクセスしてファイルを保存する * * @author bose999 * */ public class SampleBinaryClient { /** * EasyRestのURLにアクセスして アクセスしてファイルを保存する * * @param args */ public static void main(String[] args) { // RESTEasy初期化 RegisterBuiltin.register(ResteasyProviderFactory.getInstance()); // アクセスするURIをパラメータを含めて生成しリクエスト String fileName = "xxx.png"; // http://localhost:8080/sample/sampleBinrary?fileName=xxx.png というURIを生成 String uri = UriBuilder .fromUri("http://localhost:8080/sample/sampleBinrary") .queryParam("fileName", fileName).build().toString(); ClientRequest request = new ClientRequest(uri); OutputStream outputStream = null; try { // レスポンスからファイルの文字列を取得 ClientResponse<?> response = request.get(ResponseBean.class); if (response.getStatus() == 200) { ResponseBean responseBean = (ResponseBean) response.getEntity(); String fileBinaryString = responseBean.returnString; // UTF-8のBase64文字列からbyte[]を復元 byte[] decode = Base64.decodeBase64(fileBinaryString .getBytes("UTF-8")); // ファイルを生成する File outFile = new File("/data/sampleBinary/" + "return-" + fileName); outputStream = new FileOutputStream(outFile); outputStream.write(decode); } else { System.out.println("ステータスコード:" + response.getStatus()); } } catch (UnsupportedEncodingException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } catch (Exception e) { e.printStackTrace(); } finally { if (outputStream != null) { try { outputStream.close(); } catch (IOException e) { e.printStackTrace(); } } } } }