Этот код создает закрытый поток, и я не могу понять, почему. Он встроен в Apache Cloudstack, и каждый раз, когда я пытаюсь загрузить огромные файлы (например, 20 ГБ и более), возникает исключение.
Из-за getMessage () в блоке catch я даже не уверен, генерирует ли RandomAccessFile () IOException или getResponseBodyAsStream ().
К сожалению, очень сложно перекомпилировать и протестировать этот фрагмент кода, поэтому я буду очень признателен за любые подсказки, что может пойти не так.
Я попытался немного уменьшить его, но вы можете найти полную версию здесь:
https://github.com/apache/cloudstack/blob/1d05fead49f5c856257a741b07122f5633d2e359/core/src/main/java/com/cloud/storage/template/HttpTemplateDownloader.java#L184
try (InputStream in = request.getResponseBodyAsStream();
RandomAccessFile out = new RandomAccessFile(file, "rw"); ) {
out.seek(localFileSize);
if (copyBytes(file, in, out)) return 0;
} finally { /* in.close() and out.close() */ }
return totalBytes;
} catch (HttpException hte) {
status = TemplateDownloader.Status.UNRECOVERABLE_ERROR;
errorString = hte.getMessage();
} catch (IOException ioe) {
status = TemplateDownloader.Status.UNRECOVERABLE_ERROR;
errorString = ioe.getMessage();
} finally {
if (status == Status.UNRECOVERABLE_ERROR &&
file.exists() && !file.isDirectory()) {
file.delete();
}
request.releaseConnection();
if (callback != null) {
callback.downloadComplete(status);
}
}
private boolean copyBytes(File file,
InputStream in,
RandomAccessFile out) throws IOException {
int bytes;
byte[] block = new byte[CHUNK_SIZE];
long offset = 0;
boolean done = false;
VerifyFormat verifyFormat = new VerifyFormat(file);
status = Status.IN_PROGRESS;
while (!done && status != Status.ABORTED && offset <= remoteSize) {
if ((bytes = in.read(block, 0, CHUNK_SIZE)) > -1) {
offset = writeBlock(bytes, out, block, offset);
if (!verifyFormat.isVerifiedFormat() &&
(offset >= 1048576 || offset >= remoteSize)) {
//let's check format after we get 1MB or full file
verifyFormat.invoke();
if (verifyFormat.isInvalid()) return true;
}
} else {
done = true;
}
}
out.getFD().sync();
return false;
}