summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authordaniel oeh <daniel.oeh@gmail.com>2014-04-27 19:03:35 +0200
committerdaniel oeh <daniel.oeh@gmail.com>2014-04-27 19:03:35 +0200
commit00ef0f6e771f4de0230800444f50bb3a00981f0d (patch)
tree2dc6b7e70183c5e619747d1863d20d1ac1d589d9
parent6f77dea8384a90cbd6ed4ac4ce3ba4c48b7534ed (diff)
downloadAntennaPod-00ef0f6e771f4de0230800444f50bb3a00981f0d.zip
Resume failed downloads. closes #168
-rw-r--r--src/de/danoeh/antennapod/service/download/DownloadService.java11
-rw-r--r--src/de/danoeh/antennapod/service/download/HttpDownloader.java45
2 files changed, 48 insertions, 8 deletions
diff --git a/src/de/danoeh/antennapod/service/download/DownloadService.java b/src/de/danoeh/antennapod/service/download/DownloadService.java
index 855f33a3f..2d82d8631 100644
--- a/src/de/danoeh/antennapod/service/download/DownloadService.java
+++ b/src/de/danoeh/antennapod/service/download/DownloadService.java
@@ -30,7 +30,9 @@ import de.danoeh.antennapod.syndication.handler.UnsupportedFeedtypeException;
import de.danoeh.antennapod.util.ChapterUtils;
import de.danoeh.antennapod.util.DownloadError;
import de.danoeh.antennapod.util.InvalidFeedException;
+import org.apache.commons.io.FileUtils;
import org.apache.commons.lang3.StringUtils;
+import org.apache.http.HttpStatus;
import org.xml.sax.SAXException;
import javax.xml.parsers.ParserConfigurationException;
@@ -160,7 +162,14 @@ public class DownloadService extends Service {
if (!status.isCancelled()) {
if (status.getReason() == DownloadError.ERROR_UNAUTHORIZED) {
postAuthenticationNotification(downloader.getDownloadRequest());
- } else {
+ } else if (status.getReason() == DownloadError.ERROR_HTTP_DATA_ERROR
+ && Integer.valueOf(status.getReasonDetailed()) == HttpStatus.SC_REQUESTED_RANGE_NOT_SATISFIABLE) {
+
+ Log.d(TAG, "Requested invalid range, restarting download from the beginning");
+ FileUtils.deleteQuietly(new File(downloader.getDownloadRequest().getDestination()));
+ DownloadRequester.getInstance().download(DownloadService.this, downloader.getDownloadRequest());
+ }
+ else {
Log.e(TAG, "Download failed");
saveDownloadStatus(status);
handleFailedDownload(status, downloader.getDownloadRequest());
diff --git a/src/de/danoeh/antennapod/service/download/HttpDownloader.java b/src/de/danoeh/antennapod/service/download/HttpDownloader.java
index ca6655002..7ae96dc07 100644
--- a/src/de/danoeh/antennapod/service/download/HttpDownloader.java
+++ b/src/de/danoeh/antennapod/service/download/HttpDownloader.java
@@ -14,10 +14,12 @@ import org.apache.commons.lang3.StringUtils;
import org.apache.http.Header;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
+import org.apache.http.HttpStatus;
import org.apache.http.auth.UsernamePasswordCredentials;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.auth.BasicScheme;
+import org.apache.http.message.BasicHeader;
import java.io.*;
import java.net.HttpURLConnection;
@@ -36,7 +38,9 @@ public class HttpDownloader extends Downloader {
@Override
protected void download() {
File destination = new File(request.getDestination());
- if (destination.exists()) {
+ final boolean fileExists = destination.exists();
+
+ if (request.isDeleteOnFailure() && fileExists) {
Log.w(TAG, "File already exists");
if (request.getFeedfileType() != FeedImage.FEEDFILETYPE_FEEDIMAGE) {
onFail(DownloadError.ERROR_FILE_EXISTS, null);
@@ -48,10 +52,12 @@ public class HttpDownloader extends Downloader {
}
HttpClient httpClient = AntennapodHttpClient.getHttpClient();
- BufferedOutputStream out = null;
+ RandomAccessFile out = null;
InputStream connection = null;
try {
HttpGet httpGet = new HttpGet(URIUtil.getURIFromRequestUrl(request.getSource()));
+
+ // add authentication information
String userInfo = httpGet.getURI().getUserInfo();
if (userInfo != null) {
String[] parts = userInfo.split(":");
@@ -64,6 +70,15 @@ public class HttpDownloader extends Downloader {
httpGet.addHeader(BasicScheme.authenticate(new UsernamePasswordCredentials(request.getUsername(),
request.getPassword()), "UTF-8", false));
}
+
+ // add range header if necessary
+ if (fileExists) {
+ request.setSoFar(destination.length());
+ httpGet.addHeader(new BasicHeader("Range",
+ "bytes=" + request.getSoFar() + "-"));
+ if (BuildConfig.DEBUG) Log.d(TAG, "Adding range header: " + request.getSoFar());
+ }
+
HttpResponse response = httpClient.execute(httpGet);
HttpEntity httpEntity = response.getEntity();
int responseCode = response.getStatusLine().getStatusCode();
@@ -75,7 +90,7 @@ public class HttpDownloader extends Downloader {
if (BuildConfig.DEBUG)
Log.d(TAG, "Response code is " + responseCode);
- if (responseCode != HttpURLConnection.HTTP_OK || httpEntity == null) {
+ if (responseCode / 100 != 2 || httpEntity == null) {
final DownloadError error;
final String details;
if (responseCode == HttpURLConnection.HTTP_UNAUTHORIZED) {
@@ -96,14 +111,31 @@ public class HttpDownloader extends Downloader {
connection = new BufferedInputStream(AndroidHttpClient
.getUngzippedContent(httpEntity));
- out = new BufferedOutputStream(new FileOutputStream(
- destination));
+
+ Header[] contentRangeHeaders = (fileExists) ? response.getHeaders("Content-Range") : null;
+
+ if (fileExists && responseCode == HttpStatus.SC_PARTIAL_CONTENT
+ && contentRangeHeaders != null && contentRangeHeaders.length > 0) {
+ String start = contentRangeHeaders[0].getValue().substring("bytes ".length(),
+ contentRangeHeaders[0].getValue().indexOf("-"));
+ request.setSoFar(Long.valueOf(start));
+ Log.d(TAG, "Starting download at position " + request.getSoFar());
+
+ out = new RandomAccessFile(destination, "rw");
+ out.seek(request.getSoFar());
+ } else {
+ destination.delete();
+ destination.createNewFile();
+ out = new RandomAccessFile(destination, "rw");
+ }
+
+
byte[] buffer = new byte[BUFFER_SIZE];
int count = 0;
request.setStatusMsg(R.string.download_running);
if (BuildConfig.DEBUG)
Log.d(TAG, "Getting size of download");
- request.setSize(httpEntity.getContentLength());
+ request.setSize(httpEntity.getContentLength() + request.getSoFar());
if (BuildConfig.DEBUG)
Log.d(TAG, "Size is " + request.getSize());
if (request.getSize() < 0) {
@@ -133,7 +165,6 @@ public class HttpDownloader extends Downloader {
if (cancelled) {
onCancelled();
} else {
- out.flush();
// check if size specified in the response header is the same as the size of the
// written file. This check cannot be made if compression was used
if (!isGzip && request.getSize() != DownloadStatus.SIZE_UNKNOWN &&