use of com.liulishuo.filedownloader.stream.FileDownloadOutputStream in project FileDownloader by lingochamp.
the class FileDownloadRunnable method fetch.
/**
* @return Whether finish looper or not.
*/
@SuppressWarnings("SameReturnValue")
private boolean fetch(FileDownloadConnection connection, boolean isSucceedContinue, long soFar, long total) throws Throwable {
// fetching datum
InputStream inputStream = null;
final FileDownloadOutputStream outputStream = getOutputStream(isSucceedContinue, total);
try {
// Step 1, get input stream
inputStream = connection.getInputStream();
byte[] buff = new byte[BUFFER_SIZE];
callbackMinIntervalBytes = calculateCallbackMinIntervalBytes(total, maxProgressCount);
// enter fetching loop(Step 2->6)
do {
// Step 2, read from input stream.
int byteCount = inputStream.read(buff);
if (byteCount == -1) {
break;
}
// if (FileDownloadLog.NEED_LOG) {
// startWriteNanoTime = System.nanoTime();
// }
// Step 3, writ to file
outputStream.write(buff, 0, byteCount);
// if (FileDownloadLog.NEED_LOG) {
// currentNanoTime = System.nanoTime();
// long writeConsume = currentNanoTime - startWriteNanoTime;
// if (latestWriteNanoTime != 0) {
// FileDownloadLog.v(this, "each fetch loop consume | write consume: | %fms | %fms",
// (currentNanoTime - latestWriteNanoTime - writeConsume) / 1000000f,
// writeConsume / 1000000f);
// }
// latestWriteNanoTime = currentNanoTime;
// }
// Step 4, adapter sofar
soFar += byteCount;
// Step 5, callback on progressing
onProgress(soFar, total, outputStream);
// Step 6, check state
if (checkState()) {
// callback on paused
onPause();
return true;
}
} while (true);
// Step 7, adapter chunked transfer encoding
if (total == TOTAL_VALUE_IN_CHUNKED_RESOURCE) {
total = soFar;
}
// Step 8, Compare between the downloaded so far bytes with the total bytes.
if (soFar == total) {
// Step 9, rename the temp file to the completed file.
renameTempFile();
// Step 10, remove data from DB.
helper.remove(mId);
// callback completed
onComplete(total);
return true;
} else {
throw new RuntimeException(FileDownloadUtils.formatString("sofar[%d] not equal total[%d]", soFar, total));
}
} finally {
if (inputStream != null) {
//noinspection ThrowFromFinallyBlock
inputStream.close();
}
try {
if (outputStream != null) {
//noinspection ThrowFromFinallyBlock
outputStream.sync();
}
} finally {
//noinspection ConstantConditions
if (outputStream != null) {
//noinspection ThrowFromFinallyBlock
outputStream.close();
}
}
}
}
use of com.liulishuo.filedownloader.stream.FileDownloadOutputStream in project FileDownloader by lingochamp.
the class DownloadLaunchRunnable method handlePreAllocate.
private void handlePreAllocate(long totalLength, String path) throws IOException, IllegalAccessException {
FileDownloadOutputStream outputStream = null;
try {
if (totalLength != TOTAL_VALUE_IN_CHUNKED_RESOURCE) {
outputStream = FileDownloadUtils.createOutputStream(model.getTempFilePath());
final long breakpointBytes = new File(path).length();
final long requiredSpaceBytes = totalLength - breakpointBytes;
final long freeSpaceBytes = FileDownloadUtils.getFreeSpaceBytes(path);
if (freeSpaceBytes < requiredSpaceBytes) {
// throw a out of space exception.
throw new FileDownloadOutOfSpaceException(freeSpaceBytes, requiredSpaceBytes, breakpointBytes);
} else if (!FileDownloadProperties.getImpl().fileNonPreAllocation) {
// pre allocate.
outputStream.setLength(totalLength);
}
}
} finally {
if (outputStream != null)
outputStream.close();
}
}
use of com.liulishuo.filedownloader.stream.FileDownloadOutputStream in project FileDownloader by lingochamp.
the class FileDownloadRunnable method getOutputStream.
// ----------------------------------
private FileDownloadOutputStream getOutputStream(final boolean append, final long totalBytes) throws IOException, IllegalAccessException {
final String tempPath = model.getTempFilePath();
if (TextUtils.isEmpty(tempPath)) {
throw new RuntimeException("found invalid internal destination path, empty");
}
//noinspection ConstantConditions
if (!FileDownloadUtils.isFilenameValid(tempPath)) {
throw new RuntimeException(FileDownloadUtils.formatString("found invalid internal destination filename" + " %s", tempPath));
}
File file = new File(tempPath);
if (file.exists() && file.isDirectory()) {
throw new RuntimeException(FileDownloadUtils.formatString("found invalid internal destination path[%s]," + " & path is directory[%B]", tempPath, file.isDirectory()));
}
if (!file.exists()) {
if (!file.createNewFile()) {
throw new IOException(FileDownloadUtils.formatString("create new file error %s", file.getAbsolutePath()));
}
}
FileDownloadOutputStream outputStream = mOutputStreamCreator.create(file);
// check the available space bytes whether enough or not.
if (totalBytes > 0) {
final long breakpointBytes = file.length();
final long requiredSpaceBytes = totalBytes - breakpointBytes;
final long freeSpaceBytes = FileDownloadUtils.getFreeSpaceBytes(tempPath);
if (freeSpaceBytes < requiredSpaceBytes) {
outputStream.close();
// throw a out of space exception.
throw new FileDownloadOutOfSpaceException(freeSpaceBytes, requiredSpaceBytes, breakpointBytes);
} else if (!FileDownloadProperties.getImpl().FILE_NON_PRE_ALLOCATION) {
// pre allocate.
outputStream.setLength(totalBytes);
}
}
if (append && mOutputStreamCreator.supportSeek()) {
outputStream.seek(model.getSoFar());
}
return outputStream;
}
use of com.liulishuo.filedownloader.stream.FileDownloadOutputStream in project FileDownloader by lingochamp.
the class FetchDataTask method run.
public void run() throws IOException, IllegalAccessException, IllegalArgumentException, FileDownloadGiveUpRetryException {
if (paused)
return;
long contentLength = FileDownloadUtils.findContentLength(connectionIndex, connection);
if (contentLength == TOTAL_VALUE_IN_CHUNKED_RESOURCE) {
contentLength = FileDownloadUtils.findContentLengthFromContentRange(connection);
}
if (contentLength == 0) {
throw new FileDownloadGiveUpRetryException(FileDownloadUtils.formatString("there isn't any content need to download on %d-%d with the " + "content-length is 0", downloadId, connectionIndex));
}
if (this.contentLength > 0 && contentLength != this.contentLength) {
final String range;
if (endOffset == ConnectionProfile.RANGE_INFINITE) {
range = FileDownloadUtils.formatString("range[%d-)", currentOffset);
} else {
range = FileDownloadUtils.formatString("range[%d-%d)", currentOffset, endOffset);
}
throw new FileDownloadGiveUpRetryException(FileDownloadUtils.formatString("require %s with contentLength(%d), but the " + "backend response contentLength is %d on " + "downloadId[%d]-connectionIndex[%d], please ask your backend " + "dev to fix such problem.", range, this.contentLength, contentLength, downloadId, connectionIndex));
}
final long fetchBeginOffset = currentOffset;
// start fetch
InputStream inputStream = null;
FileDownloadOutputStream outputStream = null;
try {
final boolean isSupportSeek = CustomComponentHolder.getImpl().isSupportSeek();
if (hostRunnable != null && !isSupportSeek) {
throw new IllegalAccessException("can't using multi-download when the output stream can't support seek");
}
this.outputStream = outputStream = FileDownloadUtils.createOutputStream(path);
if (isSupportSeek) {
outputStream.seek(currentOffset);
}
if (FileDownloadLog.NEED_LOG) {
FileDownloadLog.d(this, "start fetch(%d): range [%d, %d), seek to[%d]", connectionIndex, startOffset, endOffset, currentOffset);
}
inputStream = connection.getInputStream();
byte[] buff = new byte[BUFFER_SIZE];
if (paused)
return;
do {
int byteCount = inputStream.read(buff);
if (byteCount == -1) {
break;
}
outputStream.write(buff, 0, byteCount);
currentOffset += byteCount;
// callback progress
callback.onProgress(byteCount);
checkAndSync();
// check status
if (paused)
return;
if (isWifiRequired && FileDownloadUtils.isNetworkNotOnWifiType()) {
throw new FileDownloadNetworkPolicyException();
}
} while (true);
} finally {
if (inputStream != null) {
try {
inputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
try {
if (outputStream != null)
sync();
} finally {
if (outputStream != null) {
try {
outputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
final long fetchedLength = currentOffset - fetchBeginOffset;
if (contentLength != TOTAL_VALUE_IN_CHUNKED_RESOURCE && contentLength != fetchedLength) {
throw new FileDownloadGiveUpRetryException(FileDownloadUtils.formatString("fetched length[%d] != content length[%d]," + " range[%d, %d) offset[%d] fetch begin offset[%d]", fetchedLength, contentLength, startOffset, endOffset, currentOffset, fetchBeginOffset));
}
// callback completed
callback.onCompleted(hostRunnable, startOffset, endOffset);
}
Aggregations