From c52c567eae4722aeabdab5fe4f515a5dd5793a6f Mon Sep 17 00:00:00 2001 From: inorichi Date: Fri, 4 Dec 2015 18:03:56 +0100 Subject: [PATCH] Avoid filename conflicts (not sure if it will be totally fixed). Check if a chapter is properly downloaded after download finishes. --- .../mangafeed/data/cache/CacheManager.java | 17 +++------- .../data/download/DownloadManager.java | 33 ++++++++++--------- .../mangafeed/data/network/NetworkHelper.java | 6 ++-- .../mangafeed/data/source/base/Source.java | 7 ++-- .../mangafeed/data/source/model/Page.java | 2 +- .../eu/kanade/mangafeed/util/DiskUtils.java | 6 ++-- 6 files changed, 34 insertions(+), 37 deletions(-) diff --git a/app/src/main/java/eu/kanade/mangafeed/data/cache/CacheManager.java b/app/src/main/java/eu/kanade/mangafeed/data/cache/CacheManager.java index 2e0e3228f..8fdb8a28a 100644 --- a/app/src/main/java/eu/kanade/mangafeed/data/cache/CacheManager.java +++ b/app/src/main/java/eu/kanade/mangafeed/data/cache/CacheManager.java @@ -179,7 +179,7 @@ public class CacheManager { return null; } - public boolean putImageToDiskCache(final String imageUrl, final Response response) { + public void putImageToDiskCache(final String imageUrl, final Response response) throws IOException { DiskLruCache.Editor editor = null; BufferedSink sink = null; @@ -187,33 +187,26 @@ public class CacheManager { String key = DiskUtils.hashKeyForDisk(imageUrl); editor = mDiskCache.edit(key); if (editor == null) { - return false; + throw new IOException("Unable to edit key"); } OutputStream outputStream = new BufferedOutputStream(editor.newOutputStream(0)); sink = Okio.buffer(Okio.sink(outputStream)); sink.writeAll(response.body().source()); - sink.flush(); mDiskCache.flush(); editor.commit(); - } catch (IOException e) { - e.printStackTrace(); - return false; + } catch (Exception e) { + throw new IOException("Unable to save image"); } finally { if (editor != null) { editor.abortUnlessCommitted(); } if (sink != null) { - try { - sink.close(); - } catch (IOException e) { - e.printStackTrace(); - } + sink.close(); } } - return true; } } diff --git a/app/src/main/java/eu/kanade/mangafeed/data/download/DownloadManager.java b/app/src/main/java/eu/kanade/mangafeed/data/download/DownloadManager.java index db8f445ef..00829b43b 100644 --- a/app/src/main/java/eu/kanade/mangafeed/data/download/DownloadManager.java +++ b/app/src/main/java/eu/kanade/mangafeed/data/download/DownloadManager.java @@ -12,8 +12,6 @@ import java.io.FileOutputStream; import java.io.FileReader; import java.io.IOException; import java.lang.reflect.Type; -import java.net.MalformedURLException; -import java.net.URL; import java.util.List; import eu.kanade.mangafeed.data.database.models.Chapter; @@ -27,6 +25,7 @@ import eu.kanade.mangafeed.data.source.model.Page; import eu.kanade.mangafeed.event.DownloadChaptersEvent; import eu.kanade.mangafeed.util.DiskUtils; import eu.kanade.mangafeed.util.DynamicConcurrentMergeOperator; +import eu.kanade.mangafeed.util.UrlUtil; import rx.Observable; import rx.Subscription; import rx.android.schedulers.AndroidSchedulers; @@ -81,6 +80,7 @@ public class DownloadManager { .lift(new DynamicConcurrentMergeOperator<>(this::downloadChapter, threadsNumber)) .onBackpressureBuffer() .observeOn(AndroidSchedulers.mainThread()) + .map(download -> areAllDownloadsFinished()) .subscribe(finished -> { if (finished) { DownloadService.stop(context); @@ -164,7 +164,7 @@ public class DownloadManager { } // Download the entire chapter - private Observable downloadChapter(Download download) { + private Observable downloadChapter(Download download) { try { DiskUtils.createDirectory(download.directory); } catch (IOException e) { @@ -182,7 +182,6 @@ public class DownloadManager { return pageListObservable .subscribeOn(Schedulers.io()) - .doOnError(error -> download.setStatus(Download.ERROR)) .doOnNext(pages -> download.setStatus(Download.DOWNLOADING)) .doOnNext(pages -> download.downloadedImages = 0) // Get all the URLs to the source images, fetch pages if necessary @@ -194,8 +193,10 @@ public class DownloadManager { .toList() .flatMap(pages -> Observable.just(download)) // If the page list threw, it will resume here - .onErrorResumeNext(error -> Observable.just(download)) - .map(d -> areAllDownloadsFinished()); + .onErrorResumeNext(error -> { + download.setStatus(Download.ERROR); + return Observable.just(download); + }); } // Get the image from the filesystem if it exists or download from network @@ -215,9 +216,9 @@ public class DownloadManager { return pageObservable // When the image is ready, set image path, progress (just in case) and status .doOnNext(p -> { - p.setImagePath(imagePath.getAbsolutePath()); - p.setProgress(100); - p.setStatus(Page.READY); + page.setImagePath(imagePath.getAbsolutePath()); + page.setProgress(100); + page.setStatus(Page.READY); download.downloadedImages++; }) // If the download fails, mark this page as error @@ -226,6 +227,7 @@ public class DownloadManager { .onErrorResumeNext(e -> Observable.just(page)); } + // Save image on disk private Observable downloadImage(Page page, Source source, File directory, String filename) { page.setStatus(Page.DOWNLOAD_IMAGE); return source.getImageProgressResponse(page) @@ -261,12 +263,7 @@ public class DownloadManager { // Get the filename for an image given the page private String getImageFilename(Page page) { - String url; - try { - url = new URL(page.getImageUrl()).getPath(); - } catch (MalformedURLException e) { - url = page.getImageUrl(); - } + String url = UrlUtil.getPath(page.getImageUrl()); return url.substring( url.lastIndexOf("/") + 1, url.length()); @@ -288,7 +285,11 @@ public class DownloadManager { // If any page has an error, the download result will be error for (Page page : download.pages) { actualProgress += page.getProgress(); - if (page.getStatus() == Page.ERROR) status = Download.ERROR; + if (page.getStatus() != Page.READY) status = Download.ERROR; + } + // Ensure that the chapter folder has all the images + if (!isChapterDownloaded(download.directory, download.pages)) { + status = Download.ERROR; } download.totalProgress = actualProgress; download.setStatus(status); diff --git a/app/src/main/java/eu/kanade/mangafeed/data/network/NetworkHelper.java b/app/src/main/java/eu/kanade/mangafeed/data/network/NetworkHelper.java index 2f05e3850..8260209df 100644 --- a/app/src/main/java/eu/kanade/mangafeed/data/network/NetworkHelper.java +++ b/app/src/main/java/eu/kanade/mangafeed/data/network/NetworkHelper.java @@ -42,7 +42,7 @@ public final class NetworkHelper { } catch (Throwable e) { return Observable.error(e); } - }).retry(3); + }).retry(2); } public Observable mapResponseToString(final Response response) { @@ -72,7 +72,7 @@ public final class NetworkHelper { } catch (Throwable e) { return Observable.error(e); } - }).retry(3); + }).retry(2); } public Observable getProgressResponse(final String url, final Headers headers, final ProgressListener listener) { @@ -96,7 +96,7 @@ public final class NetworkHelper { } catch (Throwable e) { return Observable.error(e); } - }).retry(3); + }).retry(2); } public CookieStore getCookies() { diff --git a/app/src/main/java/eu/kanade/mangafeed/data/source/base/Source.java b/app/src/main/java/eu/kanade/mangafeed/data/source/base/Source.java index 660869801..6466daa88 100644 --- a/app/src/main/java/eu/kanade/mangafeed/data/source/base/Source.java +++ b/app/src/main/java/eu/kanade/mangafeed/data/source/base/Source.java @@ -8,6 +8,7 @@ import com.squareup.okhttp.Response; import org.jsoup.Jsoup; +import java.io.IOException; import java.util.ArrayList; import java.util.List; import java.util.Map; @@ -153,8 +154,10 @@ public abstract class Source extends BaseSource { page.setStatus(Page.DOWNLOAD_IMAGE); return getImageProgressResponse(page) .flatMap(resp -> { - if (!cacheManager.putImageToDiskCache(page.getImageUrl(), resp)) { - throw new IllegalStateException("Unable to save image"); + try { + cacheManager.putImageToDiskCache(page.getImageUrl(), resp); + } catch (IOException e) { + return Observable.error(e); } return Observable.just(page); }); diff --git a/app/src/main/java/eu/kanade/mangafeed/data/source/model/Page.java b/app/src/main/java/eu/kanade/mangafeed/data/source/model/Page.java index 6ccdce66f..cbcbcc2d8 100644 --- a/app/src/main/java/eu/kanade/mangafeed/data/source/model/Page.java +++ b/app/src/main/java/eu/kanade/mangafeed/data/source/model/Page.java @@ -8,7 +8,7 @@ public class Page implements ProgressListener { private int pageNumber; private String url; private String imageUrl; - private String imagePath; + private transient String imagePath; private transient volatile int status; private transient volatile int progress; diff --git a/app/src/main/java/eu/kanade/mangafeed/util/DiskUtils.java b/app/src/main/java/eu/kanade/mangafeed/util/DiskUtils.java index c89edfea4..c0b62b5da 100644 --- a/app/src/main/java/eu/kanade/mangafeed/util/DiskUtils.java +++ b/app/src/main/java/eu/kanade/mangafeed/util/DiskUtils.java @@ -130,13 +130,13 @@ public final class DiskUtils { try { bufferedSink = Okio.buffer(Okio.sink(writeFile)); bufferedSink.writeAll(bufferedSource); - bufferedSink.close(); } catch (Exception e) { + writeFile.delete(); + throw new IOException("Unable to save image"); + } finally { if (bufferedSink != null) { bufferedSink.close(); } - writeFile.delete(); - throw new IOException("Failed saving image"); } return writeFile;