Refactor SpiderDen
This commit is contained in:
1 parent
e10e1c665f
commit
cf31a31430
2 files changed
+70
-127
No files matched your search
@@ -17,6 +17,7 @@
|
||||
|
||||
package com.hippo.ehviewer.spider
|
||||
|
||||
import android.webkit.MimeTypeMap
|
||||
import coil.annotation.ExperimentalCoilApi
|
||||
import coil.disk.DiskCache
|
||||
import com.hippo.Native.mapFd
|
||||
@@ -30,23 +31,19 @@ import com.hippo.ehviewer.client.data.GalleryInfo
|
||||
import com.hippo.ehviewer.gallery.PageLoader2
|
||||
import com.hippo.image.Image.ByteBufferSource
|
||||
import com.hippo.io.UniFileInputStreamPipe
|
||||
import com.hippo.io.UniFileOutputStreamPipe
|
||||
import com.hippo.streampipe.InputStreamPipe
|
||||
import com.hippo.streampipe.OutputStreamPipe
|
||||
import com.hippo.unifile.RawFile
|
||||
import com.hippo.unifile.UniFile
|
||||
import com.hippo.yorozuya.FileUtils
|
||||
import com.hippo.yorozuya.IOUtils
|
||||
import com.hippo.yorozuya.MathUtils
|
||||
import com.hippo.yorozuya.Utilities
|
||||
import okio.buffer
|
||||
import okio.sink
|
||||
import okhttp3.ResponseBody
|
||||
import java.io.File
|
||||
import java.io.FileInputStream
|
||||
import java.io.FileOutputStream
|
||||
import java.io.IOException
|
||||
import java.io.InputStream
|
||||
import java.io.OutputStream
|
||||
import java.io.RandomAccessFile
|
||||
import java.nio.ByteBuffer
|
||||
import java.nio.channels.FileChannel
|
||||
@@ -177,63 +174,59 @@ class SpiderDen(private val mGalleryInfo: GalleryInfo) {
|
||||
return removeFromCache(index) or removeFromDownloadDir(index)
|
||||
}
|
||||
|
||||
private fun openCacheOutputStreamPipe(index: Int, extension: String): OutputStreamPipe? {
|
||||
val key = EhCacheKeyFactory.getImageKey(mGid, index)
|
||||
val editor = sCache.edit(key) ?: return null
|
||||
try {
|
||||
editor.metadata.toFile().sink().buffer().use { sink -> sink.writeUtf8(extension) }
|
||||
} catch (e: IOException) {
|
||||
e.printStackTrace()
|
||||
}
|
||||
return object : OutputStreamPipe {
|
||||
private var os: OutputStream? = null
|
||||
override fun release() {
|
||||
editor.commit()
|
||||
}
|
||||
|
||||
@Throws(IOException::class)
|
||||
override fun open(): OutputStream {
|
||||
if (os != null) IOUtils.closeQuietly(os)
|
||||
os = FileOutputStream(editor.data.toFile())
|
||||
return os!!
|
||||
}
|
||||
|
||||
override fun close() {
|
||||
if (os != null) IOUtils.closeQuietly(os)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param extension without dot
|
||||
*/
|
||||
private fun openDownloadOutputStreamPipe(index: Int, extension: String): OutputStreamPipe? {
|
||||
var extension = extension
|
||||
private fun findDownloadFileForIndex(index: Int, extension: String): UniFile? {
|
||||
val dir = downloadDir ?: return null
|
||||
extension = fixExtension(".$extension")
|
||||
val file = dir.createFile(generateImageFilename(index, extension))
|
||||
return file?.let { UniFileOutputStreamPipe(it) }
|
||||
val ext = fixExtension(".$extension")
|
||||
return dir.createFile(generateImageFilename(index, ext))
|
||||
}
|
||||
|
||||
fun openOutputStreamPipe(index: Int, extension: String): OutputStreamPipe? {
|
||||
return when (mMode) {
|
||||
SpiderQueen.MODE_READ -> {
|
||||
// Return the download pipe is the gallery has been downloaded
|
||||
var pipe = openDownloadOutputStreamPipe(index, extension)
|
||||
if (pipe == null) {
|
||||
pipe = openCacheOutputStreamPipe(index, extension)
|
||||
// TODO: Support cancellation after spiderqueen coroutinize
|
||||
fun saveFromBufferedSource(index: Int, body: ResponseBody, notifyProgress: (Long, Long, Int) -> Unit): Long {
|
||||
val extension = MimeTypeMap.getSingleton().getExtensionFromMimeType(body.contentType().toString()) ?: "jpg"
|
||||
|
||||
fun doSave(outChannel: FileChannel): Long {
|
||||
var receivedSize: Long = 0
|
||||
body.source().use { source ->
|
||||
while (true) {
|
||||
val bytesRead = outChannel.transferFrom(source, receivedSize, TRANSFER_BLOCK)
|
||||
receivedSize += bytesRead
|
||||
notifyProgress(body.contentLength(), receivedSize, bytesRead.toInt())
|
||||
if (bytesRead.toInt() == 0) break
|
||||
}
|
||||
pipe
|
||||
}
|
||||
return receivedSize
|
||||
}
|
||||
|
||||
SpiderQueen.MODE_DOWNLOAD -> {
|
||||
openDownloadOutputStreamPipe(index, extension)
|
||||
findDownloadFileForIndex(index, extension)?.runCatching {
|
||||
openOutputStream().use { outputStream ->
|
||||
(outputStream as FileOutputStream).channel.use { return doSave(it) }
|
||||
}
|
||||
}?.onFailure {
|
||||
it.printStackTrace()
|
||||
return -1
|
||||
}
|
||||
|
||||
else -> {
|
||||
null
|
||||
// Read Mode, allow save to cache
|
||||
if (mMode == SpiderQueen.MODE_READ) {
|
||||
val key = EhCacheKeyFactory.getImageKey(mGid, index)
|
||||
val editor = sCache.edit(key) ?: return -1
|
||||
var received: Long = 0
|
||||
runCatching {
|
||||
editor.metadata.toFile().writeText(extension)
|
||||
FileOutputStream(editor.data.toFile()).use { outputStream ->
|
||||
outputStream.channel.use { received = doSave(it) }
|
||||
}
|
||||
}.onFailure {
|
||||
editor.abort()
|
||||
it.printStackTrace()
|
||||
return -1
|
||||
}.onSuccess {
|
||||
editor.commit()
|
||||
return received
|
||||
}
|
||||
}
|
||||
|
||||
return -1
|
||||
}
|
||||
|
||||
private fun openCacheInputStreamPipe(index: Int): InputStreamPipe? {
|
||||
@@ -371,6 +364,8 @@ class SpiderDen(private val mGalleryInfo: GalleryInfo) {
|
||||
}
|
||||
|
||||
companion object {
|
||||
private const val TRANSFER_BLOCK: Long = 40960
|
||||
|
||||
// We use data to store image file, and metadata for image type
|
||||
private val sCache by lazy {
|
||||
DiskCache.Builder().directory(File(application.cacheDir, "gallery_image"))
|
||||
|
||||
@@ -46,7 +46,6 @@ import com.hippo.ehviewer.client.parser.GalleryPageParser;
|
||||
import com.hippo.ehviewer.client.parser.GalleryPageUrlParser;
|
||||
import com.hippo.image.Image;
|
||||
import com.hippo.streampipe.InputStreamPipe;
|
||||
import com.hippo.streampipe.OutputStreamPipe;
|
||||
import com.hippo.unifile.UniFile;
|
||||
import com.hippo.util.ExceptionUtils;
|
||||
import com.hippo.yorozuya.IOUtils;
|
||||
@@ -57,7 +56,6 @@ import com.hippo.yorozuya.thread.PriorityThread;
|
||||
import com.hippo.yorozuya.thread.PriorityThreadFactory;
|
||||
|
||||
import java.io.BufferedInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
@@ -77,11 +75,9 @@ import java.util.concurrent.atomic.AtomicReference;
|
||||
|
||||
import eu.kanade.tachiyomi.ui.reader.loader.PageLoader;
|
||||
import okhttp3.Call;
|
||||
import okhttp3.MediaType;
|
||||
import okhttp3.OkHttpClient;
|
||||
import okhttp3.Request;
|
||||
import okhttp3.Response;
|
||||
import okhttp3.ResponseBody;
|
||||
|
||||
public final class SpiderQueen implements Runnable {
|
||||
|
||||
@@ -1213,7 +1209,6 @@ public final class SpiderQueen implements Runnable {
|
||||
|
||||
Call call = mHttpClient.newCall(new EhRequestBuilder(targetImageUrl, referer).build());
|
||||
Response response = call.execute();
|
||||
ResponseBody responseBody = response.body();
|
||||
|
||||
if (response.code() >= 400) {
|
||||
// Maybe 404
|
||||
@@ -1223,78 +1218,31 @@ public final class SpiderQueen implements Runnable {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Get extension
|
||||
String extension = null;
|
||||
MediaType mediaType = responseBody.contentType();
|
||||
if (mediaType != null) {
|
||||
extension = MimeTypeMap.getSingleton().getExtensionFromMimeType(mediaType.toString());
|
||||
var body = response.body();
|
||||
var received = mSpiderDen.saveFromBufferedSource(index, body , (contentLength, receivedSize, bytesRead) -> {
|
||||
mPagePercentMap.put(index, (float) receivedSize / contentLength);
|
||||
notifyPageDownload(index, contentLength, receivedSize, bytesRead);
|
||||
return null;
|
||||
});
|
||||
var contentLength = body.contentLength();
|
||||
body.close();
|
||||
response.close();
|
||||
|
||||
if (received == -1) {
|
||||
error = GetText.getString(R.string.error_write_failed);
|
||||
response.close();
|
||||
break;
|
||||
}
|
||||
|
||||
OutputStreamPipe osPipe = null;
|
||||
try {
|
||||
// Get out put pipe
|
||||
osPipe = mSpiderDen.openOutputStreamPipe(index, extension);
|
||||
if (osPipe == null) {
|
||||
// Can't get pipe
|
||||
error = GetText.getString(R.string.error_write_failed);
|
||||
response.close();
|
||||
break;
|
||||
}
|
||||
|
||||
long contentLength = responseBody.contentLength();
|
||||
long receivedSize = 0;
|
||||
OutputStream os = osPipe.open();
|
||||
if (os instanceof FileOutputStream fileOutputStream) {
|
||||
try (var channel = fileOutputStream.getChannel(); var source = responseBody.source(); responseBody; response) {
|
||||
while (!mStoped) {
|
||||
// Is 40k a good size ?
|
||||
long bytesRead = channel.transferFrom(source, receivedSize, 40960);
|
||||
if (bytesRead == 0) {
|
||||
break;
|
||||
}
|
||||
receivedSize += bytesRead;
|
||||
if (contentLength > 0) {
|
||||
mPagePercentMap.put(index, (float) receivedSize / contentLength);
|
||||
}
|
||||
notifyPageDownload(index, contentLength, receivedSize, (int) bytesRead);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
final byte[] data = new byte[1024 * 4];
|
||||
try (var is = responseBody.byteStream(); responseBody; response) {
|
||||
while (!mStoped) {
|
||||
int bytesRead = is.read(data);
|
||||
if (bytesRead == -1) {
|
||||
break;
|
||||
}
|
||||
os.write(data, 0, bytesRead);
|
||||
receivedSize += bytesRead;
|
||||
// Update page percent
|
||||
if (contentLength > 0) {
|
||||
mPagePercentMap.put(index, (float) receivedSize / contentLength);
|
||||
}
|
||||
// Notify listener
|
||||
notifyPageDownload(index, contentLength, receivedSize, bytesRead);
|
||||
}
|
||||
os.flush();
|
||||
}
|
||||
}
|
||||
|
||||
// check download size
|
||||
if (contentLength >= 0) {
|
||||
if (receivedSize < contentLength) {
|
||||
Log.e(TAG, "Can't download all of image data");
|
||||
error = "Incomplete";
|
||||
forceHtml = true;
|
||||
continue;
|
||||
} else if (receivedSize > contentLength) {
|
||||
Log.w(TAG, "Received data is more than contentLength");
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
if (osPipe != null) {
|
||||
osPipe.close();
|
||||
osPipe.release();
|
||||
// check download size
|
||||
if (contentLength >= 0) {
|
||||
if (received < contentLength) {
|
||||
Log.e(TAG, "Can't download all of image data");
|
||||
error = "Incomplete";
|
||||
forceHtml = true;
|
||||
continue;
|
||||
} else if (received > contentLength) {
|
||||
Log.w(TAG, "Received data is more than contentLength");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in new issue
Block a user