Avoid filename conflicts (not sure if it will be totally fixed). Check if a chapter is properly downloaded after download finishes.

This commit is contained in:
inorichi 2015-12-04 18:03:56 +01:00
parent 260fa59799
commit c52c567eae
6 changed files with 34 additions and 37 deletions

View File

@ -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;
}
}

View File

@ -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<Boolean> downloadChapter(Download download) {
private Observable<Download> 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<Page> 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);

View File

@ -42,7 +42,7 @@ public final class NetworkHelper {
} catch (Throwable e) {
return Observable.error(e);
}
}).retry(3);
}).retry(2);
}
public Observable<String> 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<Response> 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() {

View File

@ -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);
});

View File

@ -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;

View File

@ -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;