我正在使用 Java JDK 1.7 和 Jersey Web 服务框架编写一个 Web 服务。我需要提供的其中一件事是允许经过身份验证的客户端下载某些大型数据文件(1-3 GB)。理想情况下,我希望这是一个暂停和恢复类型的可下载选项。我尝试了 jersey 多部分 API,并且能够让它在高达 400 MB 的客户端计算机上运行,但除此之外它遇到了内存不足的问题。我还担心服务器在面临同时下载请求时可能会失败。关于如何做到这一点的任何想法?Netty 是一种选择吗?关于如何将 Netty 集成到现有的基于 Jersey 的 Web 服务中的任何指示?是否有其他框架作品可以帮助实现这一目标?我确实必须将 java 用于 Web 服务。任何指针都会有所帮助。
2 回答
If you are getting stuck on out-of-memory issues, you should check how you are handling the data you are downloading. If you are using Jersey's ClientResponse, make sure you are using getEntityInputStream() and not getEntity(). This way, you can stream the data, write it to file, and toss it aside, rather than letting it build up in the Java heap space.
I can't really speak about your simultaneous download concerns, but if you are using the web services framework, then it should be handled properly.
For both issues, more info on your specific implementation, especially code, will help you get a better response.
服务器和客户端都必须支持 HTTP 分块编码,这允许使用 HTTP 流式传输数据。下面的代码应该适用于 Jersey 2.11。
要下载大文件,请在服务器上尝试:
@GET
@Path("/files/{fileName}")
@Produces(MediaType.APPLICATION_OCTET_STREAM)
public StreamingOutput getFile(@PathParam("fileName") final String fileName) throws Exception {
//create instance of StreamingOutput here
return streamingOutput;
}
尝试使用 Steam 下载文件的客户端 GET 请求。
public String getFileReq(File outFile) throws IOException {
client = ClientBuilder.newClient(new ClientConfig());
client.property(ClientProperties.REQUEST_ENTITY_PROCESSING, "CHUNKED");
WebTarget target = client.target(URI)
OutputStream fileOutputStream = new FileOutputStream(outFile);
InputStream fileInputStream = target.request().get(InputStream.class);
writeFile(fileInputStream, fileOutputStream);
}
public static void writeFile(InputStream fileInputStream, OutputStream outputStream) throws IOException {
try {
byte[] buffer = new byte[1024];
int bytesRead;
while((bytesRead = fileInputStream.read(buffer)) !=-1) {
outputStream.write(buffer, 0, bytesRead);
}
fileInputStream.close();
outputStream.flush();
} catch (IOException e) {
e.printStackTrace();
} finally {
outputStream.close();
}