diff --git a/app/src/main/java/io/legado/app/ui/book/info/BookInfoViewModel.kt b/app/src/main/java/io/legado/app/ui/book/info/BookInfoViewModel.kt index 9da4a72c3..07444bc52 100644 --- a/app/src/main/java/io/legado/app/ui/book/info/BookInfoViewModel.kt +++ b/app/src/main/java/io/legado/app/ui/book/info/BookInfoViewModel.kt @@ -22,6 +22,7 @@ import io.legado.app.help.AppWebDav import io.legado.app.help.book.* import io.legado.app.help.coroutine.Coroutine import io.legado.app.lib.webdav.ObjectNotFoundException +import io.legado.app.model.analyzeRule.AnalyzeUrl import io.legado.app.model.BookCover import io.legado.app.model.ReadBook import io.legado.app.model.localBook.LocalBook @@ -242,7 +243,7 @@ class BookInfoViewModel(application: Application) : BaseViewModel(application) { webFiles.clear() val fileName = "${book.name} 作者:${book.author}" book.downloadUrls!!.map { - val mFileName = UrlUtil.getFileName(it) ?: fileName + val mFileName = UrlUtil.getFileName(AnalyzeUrl(it, source = bookSource)) ?: fileName WebFile(it, mFileName) } }.onError { @@ -456,7 +457,7 @@ class BookInfoViewModel(application: Application) : BaseViewModel(application) { } // 后缀 - val suffix: String = name.substringAfterLast(".") + val suffix: String = UrlUtil.getSuffix(name) // txt epub umd pdf等文件 val isSupported: Boolean = AppPattern.bookFileRegex.matches(name) diff --git a/app/src/main/java/io/legado/app/utils/UrlUtil.kt b/app/src/main/java/io/legado/app/utils/UrlUtil.kt index ce8b4f0b7..15c01d034 100644 --- a/app/src/main/java/io/legado/app/utils/UrlUtil.kt +++ b/app/src/main/java/io/legado/app/utils/UrlUtil.kt @@ -1,5 +1,7 @@ package io.legado.app.utils +import io.legado.app.model.analyzeRule.AnalyzeUrl +import io.legado.app.constant.AppLog import java.net.HttpURLConnection import java.net.URL import java.net.URLDecoder @@ -29,19 +31,33 @@ object UrlUtil { .replace("|", "%7C") } + + /* 阅读定义的url,{urlOption} */ + fun getFileName(analyzeUrl: AnalyzeUrl): String? { + return getFileName(analyzeUrl.url, analyzeUrl.headerMap) + } + /** - * 根据网络url获取文件名 + * 根据网络url获取文件信息 文件名 */ - fun getFileName(fileUrl: String): String? { + fun getFileName(fileUrl: String, headerMap: Map? = null): String? { + // 如果获取到后缀可直接截取链接 + if (getSuffix(fileUrl, "") != "") return fileUrl.substringAfterLast("/") return kotlin.runCatching { - var fileName: String + var fileName: String = "" val url = URL(fileUrl) val conn: HttpURLConnection = url.openConnection() as HttpURLConnection - // head方式 + // HEAD方式获取返回头信息 conn.requestMethod = "HEAD" + // 下载链接可能还需要书源header才能成功访问 + headerMap?.forEach { key, value -> + conn.setRequestProperty(key, value) + } conn.connect() - // 方法一 + // val contentLength = conn.getContentLengthLong() + // Content-Disposition + // 解析文件名 filename= filename*= val raw: String? = conn.getHeaderField("Content-Disposition") if (raw != null && raw.indexOf("=") > 0) { fileName = raw.split("=".toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray()[1] @@ -50,22 +66,39 @@ object UrlUtil { fileName.toByteArray(StandardCharsets.ISO_8859_1), StandardCharsets.UTF_8 //? ) - } else { - // 方法二 截取 + } else if (conn.getHeaderField("Location") != null) { + // Location跳转到实际的下载链接 var newUrl: String = conn.url.path ?: return null newUrl = URLDecoder.decode(newUrl, "UTF-8") - fileName = newUrl.substringAfterLast("/") + if (getSuffix(newUrl, "") != "") { + fileName = newUrl.substringAfterLast("/") + } + } else { + // 其余情况 返回响应头 + val headers = conn.getHeaderFields() + val headersString = buildString { + headers.forEach { key, value -> + value.forEach { + append(key) + append(": ") + append(it) + append("\n") + } + } + } + AppLog.putDebug("Cannot obtain URL file name:\n$headersString") } fileName }.getOrNull() } - fun getSuffix(url: String, default: String): String { - val suffix = url.substringAfterLast(".").substringBeforeLast(",") + /* 获取合法的文件后缀 */ + fun getSuffix(str: String, default: String? = null): String { + val suffix = str.substringAfterLast(".").substringBeforeLast(",") //检查截取的后缀字符是否合法 [a-zA-Z0-9] val fileSuffixRegex = Regex("^[a-z\\d]+$", RegexOption.IGNORE_CASE) return if (suffix.length > 5 || !suffix.matches(fileSuffixRegex)) { - default + default ?: throw IllegalArgumentException("Cannot find illegal suffix:\n target: $str\nsuffix: $suffix") } else { suffix }