私の画像ファイルはデータベースに保存されています。 クライアント上でそれらをレンダリングできるようにするために、データベース列からバイナリストリームを読み込んでサーブレットレスポンスの出力ストリームに書き込むのに役立つ非同期サーブレットを実装しました。従来のIOはここでうまく動作します。非同期サーブレットとファイルをダウンロードするための非ブロックIOの使用方法は?
非ブロッキングIOを非同期サーブレット(パフォーマンスをテストする)で試してみたところ、応答に返されたバイナリデータは破損しています。
Oracle Blogから、非同期NIOサーブレットを使用したファイルアップロードのさまざまな例を見てきましたが、私の問題は助けになりません。
ここでは、サーブレットのコードがあります:
私が間違って何をやっている:
@WebServlet(asyncSupported = true, urlPatterns = "/myDownloadServlet")
public class FileRetrievalServletAsyncNIO extends HttpServlet
{
private static final long serialVersionUID = -6914766655133758332L;
@Override
protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
{
Queue<byte[]> containerQueue = new LinkedList<byte[]>();
AsyncContext asyncContext = request.startAsync();
asyncContext.addListener(new AsyncListenerImpl());
asyncContext.setTimeout(120000);
try
{
long attachmentId = Long.valueOf(request.getParameter("id"));
MyAttachmentDataObject retObj = ServletUtils.fetchAttachmentHeaders(attachmentId);
response = (HttpServletResponse) asyncContext.getResponse();
response.setHeader("Content-Length", String.valueOf(retObj.getContentLength()));
if (Boolean.valueOf(request.getParameter(ServletConstants.REQ_PARAM_ENABLE_DOWNLOAD)))
response.setHeader("Content-disposition", "attachment; filename=" + retObj.getName());
response.setContentType(retObj.getContentType());
ServletOutputStream sos = response.getOutputStream();
ServletUtils.fetchContentStreamInChunks(attachmentId, containerQueue); // reads from database and adds to the queue in chunks
sos.setWriteListener(new WriteListenerImpl(sos, containerQueue, asyncContext));
}
catch (NumberFormatException | IOException exc)
{
exc.printStackTrace();
request.setAttribute("message", "Failed");
}
}
}
ここで応答データは次のようになり、ライトリスナーの実装
public class WriteListenerImpl implements WriteListener
{
private ServletOutputStream output = null;
private Queue<byte[]> queue = null;
private AsyncContext asyncContext = null;
private HttpServletRequest request = null;
private HttpServletResponse response = null;
public WriteListenerImpl(ServletOutputStream sos, Queue<byte[]> q, AsyncContext aCtx)
{
output = sos;
queue = q;
asyncContext = aCtx;
request = (HttpServletRequest) asyncContext.getRequest();
}
@Override
public void onWritePossible() throws IOException
{
while(output.isReady())
{
while (!queue.isEmpty())
{
byte[] temp = queue.poll();
output.write(temp, 0, temp.length);
}
asyncContext.complete();
request.setAttribute("message", "Success");
}
}
@Override
public void onError(Throwable t)
{
System.err.println(t);
try
{
response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
}
catch (IOException exc)
{
exc.printStackTrace();
}
request.setAttribute("message", "Failure");
asyncContext.complete();
}
}
ですか?
これはうまくいかなかった。ダウンロードしたファイルが不適切です。 – Chiranjib
ファイルの問題は何ですか? async ioを使用しようとする前に、以前にファイルに書き込んだことはありますか? – mmulholl
ファイルに問題はありません。ダウンロードは、非同期サーブレット+従来のIOで完璧に動作しています。何らかの理由で働いていないのはNIOだけです。 – Chiranjib