使用 InputStream 下载大文件
Download large files using InputStream
我们在 Linux 上有一个 Weblogic 服务器 运行ning,具有多个托管服务器。我所关注的托管服务器的最大堆大小为 1024MB。该服务器上部署了多个应用程序。其中一个应用程序处理来自 REST api 的响应以下载大至 250MB 的文件。对于大于 50 MB 的文件,有时没有问题,但有时服务器会因 OOM 错误而崩溃。
以下是我的代码:
Client client = Client.create();
WebResource webResource = client.resource(url.toString());
ClientResponse response = webResource.accept("application/json").get(ClientResponse.class);
if (response.getStatus() != 200) {
throw new RuntimeException("Failed : HTTP error code : "+ response.getStatus());
}
String output = response.getEntity(String.class);
byte[] fileContent = Base64.decodeBase64(output.getBytes());
if (fileContent != null) {
OutputStream out = null;
try {
res.reset();
out = res.getOutputStream();
res.setContentType(contentType);
res.setHeader("Content-Disposition", "inline; filename=" + fileName + "; size=" + String.valueOf(fileContent.length));
res.setContentLength(fileContent.length);
out.write(fileContent);
} catch (Exception ex) {
e.printStackTrace();
} finally {
out.flush();
out.close();
}
}
由于存在内存问题,我尝试采用InputStream的方式。以下是更改后的代码:
Client client = Client.create();
WebResource webResource = client.resource(url.toString());
ClientResponse response = webResource.accept("application/json").get(ClientResponse.class);
if (response.getStatus() != 200) {
throw new RuntimeException("Failed : HTTP error code : "+ response.getStatus());
}
InputStream source = response.getEntityInputStream(); // IS THIS OKAY?
if (source!= null) {
OutputStream out = null;
int count = 0;
try {
byte[] buffer = new byte[1024];
int read = 0;
res.reset();
res.setContentType(contentType);
res.setHeader("Content-Disposition", "inline; filename=" + fileName);
out = res.getOutputStream();
while ((read = source.read(buffer)) != -1) {
out.write(buffer, 0, read);
count++;
}
System.out.println("COUNT: " + count);// For a 60MB file, this prints 86000. why?
} catch (Exception ex) {
e.printStackTrace();
}finally{
out.flush();
out.close();
source.close();
}
此代码不会 运行 进入 OOM 但文件无法 load/is 损坏。问题是否与它是 Base64 编码的响应而我没有正确处理它有关?如果是,我该怎么办?该应用程序 运行 宁 Java 7。
我的方法使用 InputStream 来解决 OOM 好吗?该服务不以块的形式发送响应。我还有哪些其他方法可以继续?我担心我 运行 仅仅为了 50MB 的文件就陷入错误(并不总是)。
服务器是远程服务器,由另一组处理。如何检查是否有其他原因导致服务器崩溃?
您好,试试这个指南。 https://www.baeldung.com/java-download-file
这是一个很棒的网站,它提供了几乎所有可以想象的场景的许多 Java 指南。
祝你好运! :-)
我使用 Base64InputStream 来解码 InputStream 响应,它工作正常。
InputStream stream = response.getEntityInputStream();
Base64InputStream bis = new Base64InputStream(stream);
然后,用bis写文件。这种方法现在打印 65000 左右的计数变量。
我们在 Linux 上有一个 Weblogic 服务器 运行ning,具有多个托管服务器。我所关注的托管服务器的最大堆大小为 1024MB。该服务器上部署了多个应用程序。其中一个应用程序处理来自 REST api 的响应以下载大至 250MB 的文件。对于大于 50 MB 的文件,有时没有问题,但有时服务器会因 OOM 错误而崩溃。 以下是我的代码:
Client client = Client.create();
WebResource webResource = client.resource(url.toString());
ClientResponse response = webResource.accept("application/json").get(ClientResponse.class);
if (response.getStatus() != 200) {
throw new RuntimeException("Failed : HTTP error code : "+ response.getStatus());
}
String output = response.getEntity(String.class);
byte[] fileContent = Base64.decodeBase64(output.getBytes());
if (fileContent != null) {
OutputStream out = null;
try {
res.reset();
out = res.getOutputStream();
res.setContentType(contentType);
res.setHeader("Content-Disposition", "inline; filename=" + fileName + "; size=" + String.valueOf(fileContent.length));
res.setContentLength(fileContent.length);
out.write(fileContent);
} catch (Exception ex) {
e.printStackTrace();
} finally {
out.flush();
out.close();
}
}
由于存在内存问题,我尝试采用InputStream的方式。以下是更改后的代码:
Client client = Client.create();
WebResource webResource = client.resource(url.toString());
ClientResponse response = webResource.accept("application/json").get(ClientResponse.class);
if (response.getStatus() != 200) {
throw new RuntimeException("Failed : HTTP error code : "+ response.getStatus());
}
InputStream source = response.getEntityInputStream(); // IS THIS OKAY?
if (source!= null) {
OutputStream out = null;
int count = 0;
try {
byte[] buffer = new byte[1024];
int read = 0;
res.reset();
res.setContentType(contentType);
res.setHeader("Content-Disposition", "inline; filename=" + fileName);
out = res.getOutputStream();
while ((read = source.read(buffer)) != -1) {
out.write(buffer, 0, read);
count++;
}
System.out.println("COUNT: " + count);// For a 60MB file, this prints 86000. why?
} catch (Exception ex) {
e.printStackTrace();
}finally{
out.flush();
out.close();
source.close();
}
此代码不会 运行 进入 OOM 但文件无法 load/is 损坏。问题是否与它是 Base64 编码的响应而我没有正确处理它有关?如果是,我该怎么办?该应用程序 运行 宁 Java 7。 我的方法使用 InputStream 来解决 OOM 好吗?该服务不以块的形式发送响应。我还有哪些其他方法可以继续?我担心我 运行 仅仅为了 50MB 的文件就陷入错误(并不总是)。 服务器是远程服务器,由另一组处理。如何检查是否有其他原因导致服务器崩溃?
您好,试试这个指南。 https://www.baeldung.com/java-download-file
这是一个很棒的网站,它提供了几乎所有可以想象的场景的许多 Java 指南。
祝你好运! :-)
我使用 Base64InputStream 来解码 InputStream 响应,它工作正常。
InputStream stream = response.getEntityInputStream();
Base64InputStream bis = new Base64InputStream(stream);
然后,用bis写文件。这种方法现在打印 65000 左右的计数变量。