在 Jersey 2 中流式传输多部分
Streaming a multipart in Jersey 2
我目前有 Jersey REST 代码来流式传输单个文件,效果很好:
StreamingOutput stream = new StreamingOutput() {
@Override
public void write(OutputStream out)
throws IOException {
final BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(out);
// Stream is filled with data in this method.
restDAO.readData(bufferedOutputStream);
bufferedOutputStream.flush();
bufferedOutputStream.close();
}
};
return Response.ok(body, mimeType).header("filename", getFileName()).build();
但是,我想流式传输一个包含大文件和 JSON 的多部分文件,执行如下操作:
FormDataMultiPart multiPart = new FormDataMultiPart();
multiPart.bodyPart(jsonObject, MediaType.APPLICATION_JSON_TYPE);
String mimeType = "application/octet-stream";
StreamingOutput stream = new StreamingOutput() {
@Override
public void write(OutputStream out)
throws IOException {
final BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(out);
// Stream is filled with data in this method.
restDAO.readData(bufferedOutputStream);
bufferedOutputStream.flush();
bufferedOutputStream.close();
}
};
multiPart.bodyPart(stream, MediaTypeUtil.stringToMediaType(mimeType));
return Response.ok(multiPart, MediaType.MULTIPART_FORM_DATA).build();
但是,上面的代码不起作用。当 运行: javax.ws.rs.BadRequestException: HTTP 400 Bad Request
时出现此错误
是否可以用类似的方式流式传输 multiPart?我看到的主要问题是进入多部分的文件来自流本身。
为了正确流式传输多部分,我最终使用了 PipedInputStream 和 PipedOutputStream 以及一个线程:
PipedOutputStream pipedOutputStream = new PipedOutputStream();
PipedInputStream pipedInputStream = new PipedInputStream(pipedOutputStream);
final BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(pipedOutputStream);
FormDataMultiPart multiPart = new FormDataMultiPart();
multiPart.bodyPart(jsonObject, MediaType.APPLICATION_JSON_TYPE);
String mimeType = "application/octet-stream";
// Multipart streaming.
// Write to the PipedOutputStream in a separate thread
Runnable runnable = new Runnable() {
public void run() {
try {
restDAO.readData(bufferedOutputStream);
bufferedOutputStream.flush();
bufferedOutputStream.close();
} catch (Exception e) {
e.printStackTrace();
}
}
};
Thread fileThread = new Thread(runnable, "MultiPartFileStreamer");
fileThread.start();
final StreamDataBodyPart streamDataBodyPart = new StreamDataBodyPart(
"file", pipedInputStream, data.getContentFileName(),
MediaUtils.stringToMediaType(mimeType));
multiPart.bodyPart(streamDataBodyPart);
return Response.ok(multiPart, MediaType.MULTIPART_FORM_DATA).build();
我目前有 Jersey REST 代码来流式传输单个文件,效果很好:
StreamingOutput stream = new StreamingOutput() {
@Override
public void write(OutputStream out)
throws IOException {
final BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(out);
// Stream is filled with data in this method.
restDAO.readData(bufferedOutputStream);
bufferedOutputStream.flush();
bufferedOutputStream.close();
}
};
return Response.ok(body, mimeType).header("filename", getFileName()).build();
但是,我想流式传输一个包含大文件和 JSON 的多部分文件,执行如下操作:
FormDataMultiPart multiPart = new FormDataMultiPart();
multiPart.bodyPart(jsonObject, MediaType.APPLICATION_JSON_TYPE);
String mimeType = "application/octet-stream";
StreamingOutput stream = new StreamingOutput() {
@Override
public void write(OutputStream out)
throws IOException {
final BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(out);
// Stream is filled with data in this method.
restDAO.readData(bufferedOutputStream);
bufferedOutputStream.flush();
bufferedOutputStream.close();
}
};
multiPart.bodyPart(stream, MediaTypeUtil.stringToMediaType(mimeType));
return Response.ok(multiPart, MediaType.MULTIPART_FORM_DATA).build();
但是,上面的代码不起作用。当 运行: javax.ws.rs.BadRequestException: HTTP 400 Bad Request
时出现此错误是否可以用类似的方式流式传输 multiPart?我看到的主要问题是进入多部分的文件来自流本身。
为了正确流式传输多部分,我最终使用了 PipedInputStream 和 PipedOutputStream 以及一个线程:
PipedOutputStream pipedOutputStream = new PipedOutputStream();
PipedInputStream pipedInputStream = new PipedInputStream(pipedOutputStream);
final BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(pipedOutputStream);
FormDataMultiPart multiPart = new FormDataMultiPart();
multiPart.bodyPart(jsonObject, MediaType.APPLICATION_JSON_TYPE);
String mimeType = "application/octet-stream";
// Multipart streaming.
// Write to the PipedOutputStream in a separate thread
Runnable runnable = new Runnable() {
public void run() {
try {
restDAO.readData(bufferedOutputStream);
bufferedOutputStream.flush();
bufferedOutputStream.close();
} catch (Exception e) {
e.printStackTrace();
}
}
};
Thread fileThread = new Thread(runnable, "MultiPartFileStreamer");
fileThread.start();
final StreamDataBodyPart streamDataBodyPart = new StreamDataBodyPart(
"file", pipedInputStream, data.getContentFileName(),
MediaUtils.stringToMediaType(mimeType));
multiPart.bodyPart(streamDataBodyPart);
return Response.ok(multiPart, MediaType.MULTIPART_FORM_DATA).build();