ジャージーでマルチパート形式でアップロードされたファイルを読み取るサービスの開発に成功しました。これが私がやってきたことの非常に単純化されたバージョンです:
@POST
@Path("FileCollection")
@Consumes(MediaType.MULTIPART_FORM_DATA)
public Response uploadFile(@FormDataParam("file") InputStream uploadedInputStream,
@FormDataParam("file") FormDataContentDisposition fileDetail) throws IOException {
//handle the file
}
これは問題なく機能しますが、新しい要件が与えられました。アップロードするファイルに加えて、任意の数のリソースを処理する必要があります。これらが画像ファイルであると仮定しましょう。
ファイルへの入力が1つ、最初の画像への入力が1つ、フォームに入力を追加できるボタン(AJAXまたは単純なJavaScriptを使用)を備えたフォームをクライアントに提供するだけだと思いました。
<form action="blahblahblah" method="post" enctype="multipart/form-data">
<input type="file" name="file" />
<input type="file" name="image" />
<input type="button" value="add another image" />
<input type="submit" />
</form>
したがって、ユーザーは次のように、画像の入力をフォームに追加できます。
<form action="blahblahblah" method="post" enctype="multipart/form-data">
<input type="file" name="file" />
<input type="file" name="image" />
<input type="file" name="image" />
<input type="file" name="image" />
<input type="button" value="add another image" />
<input type="submit" />
</form>
コレクションと同じ名前のフィールドを読むのが簡単だといいのですが。MVC .NETのテキスト入力で問題なく実行できましたが、ジャージーではそれほど難しくないと思いました。私が間違っていたことがわかりました。
このテーマに関するチュートリアルが見つからなかったので、実験を開始しました。
それを行う方法を確認するために、私は問題を単純なテキスト入力に落とし込みました。
<form action="blahblabhblah" method="post" enctype="multipart/form-data">
<fieldset>
<legend>Multiple inputs with the same name</legend>
<input type="text" name="test" />
<input type="text" name="test" />
<input type="text" name="test" />
<input type="text" name="test" />
<input type="submit" value="Upload It" />
</fieldset>
</form>
明らかに、メソッドのパラメーターとして、ある種のコレクションが必要でした。これが私が試したもので、コレクションの種類ごとにグループ化されています。
配列
最初に、Jerseyが単純な配列を処理するのに十分賢いかどうかを確認しました。
@POST
@Path("FileCollection")
@Consumes(MediaType.MULTIPART_FORM_DATA)
public Response uploadFile(@FormDataParam("test") String[] inputs) {
//handle the request
}
しかし、アレイは期待どおりに注入されませんでした。
MultiValuedMap
惨めに失敗したので、MultiValuedMap
オブジェクトは箱から出して処理できることを思い出しました。
@POST
@Path("FileCollection")
@Consumes(MediaType.MULTIPART_FORM_DATA)
public Response uploadFile(MultiValuedMap<String, String> formData) {
//handle the request
}
しかし、それも機能しません。今回は例外がありました
SEVERE: A message body reader for Java class javax.ws.rs.core.MultivaluedMap,
and Java type javax.ws.rs.core.MultivaluedMap<java.lang.String, java.lang.String>,
and MIME media type multipart/form-data;
boundary=----WebKitFormBoundaryxgxeXiWk62fcLALU was not found.
この例外はライブラリを含めることで取り除くことができると言われたmimepull
ので、pomに次の依存関係を追加しました。
<dependency>
<groupId>org.jvnet</groupId>
<artifactId>mimepull</artifactId>
<version>1.3</version>
</dependency>
残念ながら、問題は解決しません。おそらく、適切なボディリーダーを選択し、ジェネリックにさまざまなパラメーターを使用することです。これを行う方法がわかりません。Long
ファイル入力とテキスト入力の両方、およびその他のいくつか(主に値とカスタムパラメータークラス)を使用したいと思います。
FormDataMultipart
さらに調べてみると、FormDataMultiPartクラスが見つかりました。フォームから文字列値を抽出するために正常に使用しました
@POST
@Path("upload2")
@Consumes(MediaType.MULTIPART_FORM_DATA)
public Response uploadMultipart(FormDataMultiPart multiPart){
List<FormDataBodyPart> fields = multiPart.getFields("test");
System.out.println("Name\tValue");
for(FormDataBodyPart field : fields){
System.out.println(field.getName() + "\t" + field.getValue());
//handle the values
}
//prepare the response
}
問題は、これが私の問題の単純化されたバージョンの解決策であるということです。ジャージーによって注入されたすべてのパラメーターは、ある時点で文字列を解析することによって作成されることを知っていますが(当然、それはHTTPです)、独自のパラメータークラスを作成した経験はありますが、これらのフィールドをに変換する方法は実際にはありません。InputStream
またはFile
さらに処理するためのインスタンス。
したがって、これらのオブジェクトがどのように作成されるかを確認するためにジャージーのソースコードに飛び込む前に、(サイズが不明な)ファイルのセットを読み取る簡単な方法があるかどうかをここで尋ねることにしました。この難問を解決する方法を知っていますか?