この質問を CXF リストに投稿しましたが、運がありませんでした。それでは、行きましょう。大きなファイルをリモート サーバー (仮想マシン ディスクと考えてください) にアップロードしようとしています。そのため、アップロード要求を受け入れる安らかなサービスがあります。アップロードのハンドラーは次のようになります。
@POST
@Consumes(MediaType.MULTIPART_FORM_DATA)
@Path("/doupload")
public Response receiveStream(MultipartBody multipart) {
List<Attachment> allAttachments = body.getAllAttachments();
Attachment att = null;
for (Attachment b : allAttachments) {
if (UPLOAD_FILE_DESCRIPTOR.equals(b.getContentId())) {
att = b;
}
}
Assert.notNull(att);
DataHandler dh = att.getDataHandler();
if (dh == null) {
throw new WebApplicationException(HTTP_BAD_REQUEST);
}
try {
InputStream is = dh.getInputStream();
byte[] buf = new byte[65536];
int n;
OutputStream os = getOutputStream();
while ((n = is.read(buf)) > 0) {
os.write(buf, 0, n);
}
ResponseBuilder rb = Response.status(HTTP_CREATED);
return rb.build();
} catch (IOException e) {
log.error("Got exception=", e);
throw new WebApplicationException(HTTP_INTERNAL_ERROR);
} catch (NoSuchAlgorithmException e) {
log.error("Got exception=", e);
throw new WebApplicationException(HTTP_INTERNAL_ERROR);
} finally {}
}
このコードのクライアントはかなり単純です。
public void sendLargeFile(String filename) {
WebClient wc = WebClient.create(targetUrl);
InputStream is = new FileInputStream(new File(filename));
Response r = wc.post(new Attachment(Constants.UPLOAD_FILE_DESCRIPTOR,
MediaType.APPLICATION_OCTET_STREAM, is));
}
コードは機能的には問題なく動作します。パフォーマンスに関しては、ハンドラー (receiveStream() メソッド) がストリームから最初のバイトを取得する前に、実際にストリーム全体が一時ファイルに (CachedOutputStream を使用して) 保持されることに気付きました。残念ながら、これは私の目的には受け入れられません。
- 私のハンドラーは単純に着信バイトをバックエンド ストレージ システム (仮想マシン ディスク リポジトリ) に渡します。ディスク全体がキャッシュに書き込まれ、再度読み取られるまで待機すると、多くのリソースが占有され、多くの時間がかかります。スループットを低下させます。
- アプリはクラウドで実行されており、ブロックの読み取り/書き込みごとにクラウド プロバイダーが課金するため、ブロックの書き込みと再度の読み取りに関連するコストが発生します。
- すべてのバイトがローカル ディスクに書き込まれるため、サービス VM には、アップロードされるすべてのストリームの合計サイズに対応できる十分なディスク容量が必要です (つまり、それぞれ 100 GB のアップロードが 10 回ある場合、キャッシュするためだけに 1 TB のディスクが必要です)コンテンツ)。サービス VM のサイズが劇的に増大し、クラウド プロバイダーはプロビジョニングされたディスク サイズに対しても課金するため、これも余分な費用がかかります。
これらすべてを考慮して、HTTP InputStream (またはできるだけそれに近い) を使用して、そこから添付ファイルを直接読み取り、後で処理する方法を探しています。私は質問が次のいずれかに変換されると思います:
ここで同様の質問を見つけました。解決策には、CXF 2.2.3 以降を使用するように記載されていますが、私は 2.4.4 を使用しています (そして 2.7.0 で試しました) 運がありません。
ありがとう。