我需要提供一种下载大文件的方法。
我的实现可行,但是它可能会因客户端的OutOfMemoryError而失败-有时设置更多的堆帮助,有时却没有。
我在计算机(32GB RAM)上运行良好,但在具有〜6GB的计算机上经常失败。
我的文件接近2GB。
应该进行哪些修改才能提供故障安全下载方法? 我猜entity.writeTo(...); 。 我也猜想它会将整个文件存储在内存中,而不应该这样。 如何将所有数据写入磁盘并确保没有大的内存缓冲区?
如果我从InputStream中读取byte[1024]块会有所帮助吗?
相同的问题适用于服务器。 我正在使用Files.copy(...)来传输数据,因为我在某处读取了它调用OS的API函数的信息,并且实际发生了磁盘I / O。
客户:
public boolean requestUpdateDownload(String filePath)
{
Path path = Paths.get(filePath).toAbsolutePath();
File file = path.toFile();
String url = "http://" + host + ":" + port + "/download";
System.out.println("Downloading update file from " + url);
try
{
CloseableHttpClient httpClient = HttpClients.createDefault();
HttpGet httpGet = new HttpGet(url);
CloseableHttpResponse response = httpClient.execute(httpGet);
try
{
System.out.println(response.getStatusLine());
HttpEntity entity = response.getEntity();
long expectedSize = entity.getContentLength();
if (entity != null)
{
try (FileOutputStream fileOutputStream = new FileOutputStream(file))
{
entity.writeTo(fileOutputStream);
}
}
EntityUtils.consume(entity);
long realSize = file.length();
if (expectedSize == realSize)
{
System.out.println("Received update file: " + realSize + " bytes total.");
}
else
{
System.err.println("Update file incomplete.");
deleteFile(path);
}
}
finally
{
response.close();
}
System.out.println("Saving update file to \"" + path + "\"");
System.out.println("Update file saved.");
}
catch (Exception ex)
{
System.err.println("Unable to download update file.");
ex.printStackTrace();
deleteFile(path);
return false;
}
return true;
}
服务器:
@Override
public void handle(HttpExchange httpExchange) throws IOException
{
System.out.println(LocalDateTime.now() + " Received file download request.");
String requestMethod = httpExchange.getRequestMethod();
if (requestMethod.equalsIgnoreCase("GET"))
{
Path path = Paths.get("ism","download", FILENAME);
if (Files.exists(path))
{
long size = Files.size(path);
Headers responseHeaders = httpExchange.getResponseHeaders();
responseHeaders.set("Content-Type", "application/x-7z-compressed");
responseHeaders.set("Content-Length", "" + size);
responseHeaders.set("Content-Disposition", "inline; filename=\""+ FILENAME + "\"");
httpExchange.sendResponseHeaders(200, size);
OutputStream outputStream = httpExchange.getResponseBody();
Files.copy(path, outputStream);
outputStream.close();
System.out.println(LocalDateTime.now() + " File downloaded - " + size + " bytes total.");
}
else
{
System.out.println(LocalDateTime.now() + " File does not exist.");
httpExchange.sendResponseHeaders(404, 0);
httpExchange.getResponseBody().close();
}
}
else
{
System.out.println(LocalDateTime.now() + " Method not supported.");
Headers responseHeaders = httpExchange.getResponseHeaders();
httpExchange.sendResponseHeaders(405, 0);
httpExchange.getResponseBody().close();
}
}