use of com.yanzhenjie.nohttp.error.URLError in project NoHttp by yanzhenjie.
the class Downloader method download.
public void download(int what, DownloadRequest downloadRequest, DownloadListener downloadListener) {
validateParam(downloadRequest, downloadListener);
Connection connection = null;
RandomAccessFile randomAccessFile = null;
String savePathDir = downloadRequest.getFileDir();
String fileName = downloadRequest.getFileName();
try {
if (TextUtils.isEmpty(savePathDir))
savePathDir = NoHttp.getContext().getFilesDir().getAbsolutePath();
validateDevice(savePathDir);
if (// auto named.
TextUtils.isEmpty(fileName))
fileName = Long.toString(System.currentTimeMillis());
File tempFile = new File(savePathDir, fileName + ".nohttp");
// 断点开始处。
long rangeSize = handleRange(tempFile, downloadRequest);
// 连接服务器。
connection = mHttpConnection.getConnection(downloadRequest);
Exception exception = connection.exception();
if (exception != null)
throw exception;
Logger.i("----------Response Start----------");
Headers responseHeaders = connection.responseHeaders();
int responseCode = responseHeaders.getResponseCode();
// getList filename from server.
if (downloadRequest.autoNameByHead()) {
String contentDisposition = responseHeaders.getContentDisposition();
if (!TextUtils.isEmpty(contentDisposition)) {
fileName = HeaderUtil.parseHeadValue(contentDisposition, "filename", null);
if (!TextUtils.isEmpty(fileName)) {
try {
fileName = URLDecoder.decode(fileName, downloadRequest.getParamsEncoding());
} catch (UnsupportedEncodingException e) {
// Do nothing.
}
if (fileName.startsWith("\"") && fileName.endsWith("\"")) {
fileName = fileName.substring(1, fileName.length() - 1);
}
}
}
// From url.
if (TextUtils.isEmpty(fileName)) {
String tempUrl = downloadRequest.url();
String[] slash = tempUrl.split("/");
fileName = slash[slash.length - 1];
int paramIndex = fileName.indexOf("?");
if (paramIndex > 0) {
fileName = fileName.substring(0, paramIndex);
}
}
}
InputStream serverStream = connection.serverStream();
if (responseCode >= 400) {
ServerError error = new ServerError("Download failed, the server response code is " + responseCode + ": " + downloadRequest.url());
error.setErrorBody(IOUtils.toString(serverStream));
throw error;
} else {
long contentLength;
// 文件总大小
if (responseCode == 206) {
// Content-Range: bytes [文件块的开始字节]-[文件的总大小 - 1]/[文件的总大小]。
// Sample:Accept-Range:bytes 1024-2047/2048。
String range = responseHeaders.getContentRange();
try {
// 截取'/'之后的总大小。
contentLength = Long.parseLong(range.substring(range.indexOf('/') + 1));
} catch (Throwable e) {
throw new ServerError("ResponseCode is 206, but content-Range error in Server HTTP header " + "information: " + range + ".");
}
} else if (responseCode == 304) {
int httpContentLength = responseHeaders.getContentLength();
downloadListener.onStart(what, true, httpContentLength, responseHeaders, httpContentLength);
downloadListener.onProgress(what, 100, httpContentLength, 0);
Logger.d("-------Download finish-------");
downloadListener.onFinish(what, savePathDir + File.separator + fileName);
return;
} else {
// such as: 200.
// 服务器不支持Range。
rangeSize = 0L;
// 直接下载。
contentLength = responseHeaders.getContentLength();
}
// 验证文件已经存在。
File lastFile = new File(savePathDir, fileName);
if (lastFile.exists()) {
if (downloadRequest.isDeleteOld())
IOUtils.delFileOrFolder(lastFile);
else {
downloadListener.onStart(what, true, lastFile.length(), responseHeaders, lastFile.length());
downloadListener.onProgress(what, 100, lastFile.length(), 0);
Logger.d("-------Download finish-------");
downloadListener.onFinish(what, lastFile.getAbsolutePath());
return;
}
}
if (IOUtils.getDirSize(savePathDir) < contentLength)
throw new StorageSpaceNotEnoughError("The folder is not enough space to save the downloaded file:" + " " + savePathDir + ".");
// 需要重新下载,生成临时文件。
if (responseCode != 206 && !IOUtils.createNewFile(tempFile))
throw new StorageReadWriteError("SD isn't available, please check SD card and permission: " + "WRITE_EXTERNAL_STORAGE, and you must pay attention to Android6.0 RunTime " + "Permissions: https://github.com/yanzhenjie/AndPermission.");
if (downloadRequest.isCanceled()) {
Log.w("NoHttpDownloader", "Download request is canceled.");
downloadListener.onCancel(what);
return;
}
// 通知开始下载了。
Logger.d("-------Download start-------");
downloadListener.onStart(what, rangeSize > 0, rangeSize, responseHeaders, contentLength);
randomAccessFile = new RandomAccessFile(tempFile, "rws");
randomAccessFile.seek(rangeSize);
byte[] buffer = new byte[8096];
int len;
// 旧的进度记录,防止重复通知。
int oldProgress = 0;
// 追加目前已经下载的进度。
long count = rangeSize;
long startTime = System.currentTimeMillis();
long speedCount = 0;
long oldSpeed = 0;
while (((len = serverStream.read(buffer)) != -1)) {
if (downloadRequest.isCanceled()) {
Log.i("NoHttpDownloader", "Download request is canceled.");
downloadListener.onCancel(what);
break;
} else {
randomAccessFile.write(buffer, 0, len);
count += len;
speedCount += len;
long time = System.currentTimeMillis() - startTime;
long speed = speedCount * 1000 / time;
boolean speedChanged = oldSpeed != speed && time >= 300;
Logger.i("speedCount: " + speedCount + "; time: " + time + "; speed: " + speed + "; changed: " + "" + speedChanged);
if (contentLength != 0) {
int progress = (int) (count * 100 / contentLength);
if (progress != oldProgress && speedChanged) {
downloadListener.onProgress(what, progress, count, speed);
speedCount = 0;
oldSpeed = speed;
startTime = System.currentTimeMillis();
} else if (speedChanged) {
downloadListener.onProgress(what, oldProgress, count, speed);
speedCount = 0;
oldSpeed = speed;
startTime = System.currentTimeMillis();
} else if (progress != oldProgress) {
downloadListener.onProgress(what, progress, count, oldSpeed);
}
oldProgress = progress;
} else if (speedChanged) {
downloadListener.onProgress(what, 0, count, speed);
speedCount = 0;
oldSpeed = speed;
startTime = System.currentTimeMillis();
} else {
downloadListener.onProgress(what, 0, count, oldSpeed);
}
}
}
if (!downloadRequest.isCanceled()) {
//noinspection ResultOfMethodCallIgnored
tempFile.renameTo(lastFile);
Logger.d("-------Download finish-------");
downloadListener.onFinish(what, lastFile.getAbsolutePath());
}
}
} catch (MalformedURLException e) {
Logger.e(e);
downloadListener.onDownloadError(what, new URLError(e.getMessage()));
} catch (UnknownHostException e) {
Logger.e(e);
downloadListener.onDownloadError(what, new UnKnownHostError(e.getMessage()));
} catch (SocketTimeoutException e) {
Logger.e(e);
downloadListener.onDownloadError(what, new TimeoutError(e.getMessage()));
} catch (IOException e) {
Exception newException = e;
if (!IOUtils.canWrite(savePathDir))
newException = new StorageReadWriteError("This folder cannot be written to the file: " + savePathDir + ".");
else if (IOUtils.getDirSize(savePathDir) < 1024)
newException = new StorageSpaceNotEnoughError("The folder is not enough space to save the downloaded " + "file: " + savePathDir + ".");
Logger.e(newException);
downloadListener.onDownloadError(what, newException);
} catch (Exception e) {
// NetworkError | ServerError | StorageCantWriteError | StorageSpaceNotEnoughError
if (!NetUtil.isNetworkAvailable())
e = new NetworkError("The network is not available.");
Logger.e(e);
downloadListener.onDownloadError(what, e);
} finally {
Logger.i("----------Response End----------");
IOUtils.closeQuietly(randomAccessFile);
IOUtils.closeQuietly(connection);
}
}
use of com.yanzhenjie.nohttp.error.URLError in project NoHttp by yanzhenjie.
the class HttpConnection method getConnection.
/**
* Send the request, send only head, parameters, such as file information.
*
* @param request {@link IBasicRequest}.
* @return {@link Connection}.
*/
public Connection getConnection(IBasicRequest request) {
Logger.d("--------------Request start--------------");
Headers responseHeaders = new HttpHeaders();
InputStream inputStream = null;
Exception exception = null;
Network network = null;
String url = request.url();
try {
if (!NetUtil.isNetworkAvailable())
throw new NetworkError("The network is not available, please check the network. The requested url is:" + " " + url);
// MalformedURLException, IOException, ProtocolException, UnknownHostException, SocketTimeoutException
network = createConnectionAndWriteData(request);
Logger.d("-------Response start-------");
int responseCode = network.getResponseCode();
responseHeaders = parseResponseHeaders(new URI(request.url()), responseCode, network.getResponseHeaders());
// handle body
if (responseCode == 301 || responseCode == 302 || responseCode == 303 || responseCode == 307) {
Connection redirectConnection = handleRedirect(request, responseHeaders);
responseHeaders = redirectConnection.responseHeaders();
inputStream = redirectConnection.serverStream();
exception = redirectConnection.exception();
} else if (hasResponseBody(request.getRequestMethod(), responseCode)) {
inputStream = network.getServerStream(responseCode, responseHeaders);
}
Logger.d("-------Response end-------");
} catch (MalformedURLException e) {
exception = new URLError("The url is malformed: " + url + ".");
} catch (UnknownHostException e) {
exception = new UnKnownHostError("Hostname can not be resolved: " + url + ".");
} catch (SocketTimeoutException e) {
exception = new TimeoutError("Request time out: " + url + ".");
} catch (Exception e) {
exception = e;
} finally {
if (exception != null)
Logger.e(exception);
}
Logger.d("--------------Request finish--------------");
return new Connection(network, responseHeaders, inputStream, exception);
}
Aggregations