From b9f86cbb146bf1152d155c8dcb4fdda8ca25d607 Mon Sep 17 00:00:00 2001 From: Xwite <1797350009@qq.com> Date: Thu, 16 Mar 2023 12:06:08 +0800 Subject: [PATCH] =?UTF-8?q?Localbook=E5=AE=9E=E7=8E=B0=E5=AF=BC=E5=85=A5?= =?UTF-8?q?=E5=8E=8B=E7=BC=A9=E6=96=87=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/test.yml | 2 - .../legado/app/model/localBook/LocalBook.kt | 21 ++++- .../app/ui/book/info/BookInfoActivity.kt | 20 ++--- .../app/ui/book/info/BookInfoViewModel.kt | 32 ++++---- .../java/io/legado/app/utils/ArchiveUtils.kt | 70 ++++++++++++++--- .../io/legado/app/utils/compress/RarUtils.kt | 70 ++++++++++++----- .../app/utils/compress/SevenZipUtils.kt | 76 +++++++++++++------ .../io/legado/app/utils/compress/ZipUtils.kt | 52 ++++++++++--- 8 files changed, 254 insertions(+), 89 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 161641ba3..8d3063e9f 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -2,8 +2,6 @@ name: Test Build on: push: - branches: - - master paths: - '**' - '!**/assets/**' diff --git a/app/src/main/java/io/legado/app/model/localBook/LocalBook.kt b/app/src/main/java/io/legado/app/model/localBook/LocalBook.kt index ca7a07188..bbcc528c4 100644 --- a/app/src/main/java/io/legado/app/model/localBook/LocalBook.kt +++ b/app/src/main/java/io/legado/app/model/localBook/LocalBook.kt @@ -6,6 +6,7 @@ import androidx.documentfile.provider.DocumentFile import com.script.SimpleBindings import io.legado.app.R import io.legado.app.constant.AppConst +import io.legado.app.constant.AppPattern import io.legado.app.constant.AppLog import io.legado.app.constant.BookType import io.legado.app.data.appDb @@ -31,7 +32,7 @@ import java.util.regex.Pattern /** * 书籍文件导入 目录正文解析 - * 支持在线文件(txt epub umd 压缩文件需要用户解压) 本地文件 + * 支持在线文件(txt epub umd 压缩文件 本地文件 */ object LocalBook { @@ -143,7 +144,6 @@ object LocalBook { /** * 下载在线的文件并自动导入到阅读(txt umd epub) - * 压缩文件请先提示用户解压 */ fun importFileOnLine( str: String, @@ -188,6 +188,23 @@ object LocalBook { return book } + fun importArchiveFile( + uri: Uri, + saveFileName: String, + filter: ((String) -> Boolean)? = null + ): List { + val files = ArchiveUtils.deCompress(uri, filter = filter) + if (files.isEmpty()) throw NoStackTraceException(appCtx.getString(R.string.unsupport_archivefile_entry)) + return files.map { + saveBookFile( + FileInputStream(it), + saveFileName + ).let { + importFile(it) + } + } + } + /** * 从文件分析书籍必要信息(书名 作者等) */ diff --git a/app/src/main/java/io/legado/app/ui/book/info/BookInfoActivity.kt b/app/src/main/java/io/legado/app/ui/book/info/BookInfoActivity.kt index c3763fb56..81ec2e4d1 100644 --- a/app/src/main/java/io/legado/app/ui/book/info/BookInfoActivity.kt +++ b/app/src/main/java/io/legado/app/ui/book/info/BookInfoActivity.kt @@ -534,13 +534,13 @@ class BookInfoActivity : } else if (webFile.isSupportDecompress) { /* 解压筛选后再选择导入项 */ viewModel.importOrDownloadWebFile(webFile) { uri -> - viewModel.deCompress(uri) { files -> - if (files.size == 1) { - viewModel.importBook(files[0]) { + viewModel.getArchiveEntriesName(uri) { fileNames -> + if (fileNames.size == 1) { + viewModel.importArchiveBook(uri, fileNames[0]) { onClick?.invoke(it) } } else { - showDecompressFileImportAlert(files, onClick) + showDecompressFileImportAlert(uri, fileNames, onClick) } } } @@ -562,19 +562,19 @@ class BookInfoActivity : } private fun showDecompressFileImportAlert( - files: List, + archiveFileUri: Uri, + fileNames: List, success: ((Book) -> Unit)? = null ) { - if (files.isEmpty()) { + if (fileNames.isEmpty()) { toastOnUi(R.string.unsupport_archivefile_entry) return } - val selectorNames = files.map { it.name } selector( R.string.import_select_book, - selectorNames - ) { _, _, index -> - viewModel.importBook(files[index]) { + fileNames + ) { _, name, _ -> + viewModel.importArchiveBook(archiveFileUri, name) { success?.invoke(it) } } 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 07444bc52..ea2fe20cc 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 @@ -289,17 +289,17 @@ class BookInfoViewModel(application: Application) : BaseViewModel(application) { } } - fun deCompress(archiveFileUri: Uri, onSuccess: (List) -> Unit) { + fun getArchiveEntriesName(archiveFileUri: Uri, onSuccess: (List) -> Unit) { execute { - ArchiveUtils.deCompress(archiveFileUri).filter { - AppPattern.bookFileRegex.matches(it.name) + ArchiveUtils.getArchiveFilesName(archiveFileUri) { + AppPattern.bookFileRegex.matches(it) } }.onError { when (it) { is UnsupportedRarV5Exception -> context.toastOnUi("暂不支持 rar v5 解压") else -> { - AppLog.put("DeCompress Error:\n${it.localizedMessage}", it) - context.toastOnUi("DeCompress Error:\n${it.localizedMessage}") + AppLog.put("getArchiveEntriesName Error:\n${it.localizedMessage}", it) + context.toastOnUi("getArchiveEntriesName Error:\n${it.localizedMessage}") } } }.onSuccess { @@ -308,19 +308,25 @@ class BookInfoViewModel(application: Application) : BaseViewModel(application) { } @Suppress("BlockingMethodInNonBlockingContext") - fun importBook(file: File, success: ((Book) -> Unit)? = null) { + fun importArchiveBook( + archiveFileUri: Uri, + archiveEntryName: String, + success: ((Book) -> Unit)? = null + ) { execute { - val suffix = file.name.substringAfterLast(".") - LocalBook.saveBookFile( - FileInputStream(file), + val suffix = archiveEntryName.substringAfterLast(".") + LocalBook.importArchiveFile( + archiveFileUri, bookData.value!!.getExportFileName(suffix) - ) + ) { + it.contains(archiveEntryName) + }.first() }.onSuccess { - val book = changeToLocalBook(LocalBook.importFile(it)) + val book = changeToLocalBook(it) success?.invoke(book) }.onError { - AppLog.put("ImportBook Error:\n${it.localizedMessage}", it) - context.toastOnUi("ImportBook Error:\n${it.localizedMessage}") + AppLog.put("importArchiveBook Error:\n${it.localizedMessage}", it) + context.toastOnUi("importArchiveBook Error:\n${it.localizedMessage}") } } diff --git a/app/src/main/java/io/legado/app/utils/ArchiveUtils.kt b/app/src/main/java/io/legado/app/utils/ArchiveUtils.kt index e9397bae4..83a7f00da 100644 --- a/app/src/main/java/io/legado/app/utils/ArchiveUtils.kt +++ b/app/src/main/java/io/legado/app/utils/ArchiveUtils.kt @@ -20,50 +20,96 @@ object ArchiveUtils { fun deCompress( archiveUri: Uri, - path: String = TEMP_PATH + path: String = TEMP_PATH, + filter: ((String) -> Boolean)? = null ): List { - return deCompress(FileDoc.fromUri(archiveUri, false), path) + return deCompress(FileDoc.fromUri(archiveUri, false), path, filter) } fun deCompress( archivePath: String, - path: String = TEMP_PATH + path: String = TEMP_PATH, + filter: ((String) -> Boolean)? = null ): List { - return deCompress(Uri.parse(archivePath), path) + return deCompress(Uri.parse(archivePath), path, filter) } fun deCompress( archiveFile: File, - path: String = TEMP_PATH + path: String = TEMP_PATH, + filter: ((String) -> Boolean)? = null ): List { - return deCompress(FileDoc.fromFile(archiveFile), path) + return deCompress(FileDoc.fromFile(archiveFile), path, filter) } fun deCompress( archiveDoc: DocumentFile, - path: String = TEMP_PATH + path: String = TEMP_PATH, + filter: ((String) -> Boolean)? = null ): List { - return deCompress(FileDoc.fromDocumentFile(archiveDoc), path) + return deCompress(FileDoc.fromDocumentFile(archiveDoc), path, filter) } fun deCompress( archiveFileDoc: FileDoc, - path: String = TEMP_PATH + path: String = TEMP_PATH, + filter: ((String) -> Boolean)? = null ): List { if (archiveFileDoc.isDir) throw IllegalArgumentException("Unexpected Folder input") val name = archiveFileDoc.name + checkAchieve(name) val workPathFileDoc = getCacheFolderFileDoc(name, path) val workPath = workPathFileDoc.toString() return archiveFileDoc.openInputStream().getOrThrow().use { when { - name.endsWith(".zip", ignoreCase = true) -> ZipUtils.unZipToPath(it, workPath) - name.endsWith(".rar", ignoreCase = true) -> RarUtils.unRarToPath(it, workPath) - name.endsWith(".7z", ignoreCase = true) -> SevenZipUtils.un7zToPath(it, workPath) + name.endsWith(".zip", ignoreCase = true) -> ZipUtils.unZipToPath(it, workPath, filter) + name.endsWith(".rar", ignoreCase = true) -> RarUtils.unRarToPath(it, workPath, filter) + name.endsWith(".7z", ignoreCase = true) -> SevenZipUtils.un7zToPath(it, workPath, filter) else -> throw IllegalArgumentException("Unexpected archive format") } } } + /* 遍历目录获取文件名 */ + fun getArchiveFilesName(fileUri: Uri, filter: ((String) -> Boolean)? = null): List = getArchiveEntriesName(FileDoc.fromUri(fileUri, false), filter) + + fun getArchiveFilesName( + fileDoc: FileDoc, + filter: ((String) -> Boolean)? = null + ): List { + val name = fileDoc.name + checkAchieve(name) + return fileDoc.openInputStream().getOrThrow().use { + when { + name.endsWith(".rar", ignoreCase = true) -> { + RarUtils.getFilesName(it) { + filter?.invoke(it) + } + } + name.endsWith(".zip", ignoreCase = true) -> { + ZipUtils.getFilesName(it) { + filter?.invoke(it) + } + } + name.endsWith(".7z", ignoreCase = true) -> { + SevenZipUtils.getFilesName(it) { + filter?.invoke(it) + } + } + else -> emptyList() + } + } + } + + fun checkAchieve(name: String) { + if ( + name.endsWith(".zip", ignoreCase = true) || + name.endsWith(".rar", ignoreCase = true) || + name.endsWith(".7z", ignoreCase = true) + ) return + throw IllegalArgumentException("Unexpected file suffix: Only 7z rar zip Accepted") + } + private fun getCacheFolderFileDoc( archiveName: String, workPath: String diff --git a/app/src/main/java/io/legado/app/utils/compress/RarUtils.kt b/app/src/main/java/io/legado/app/utils/compress/RarUtils.kt index 89c19bea6..ab3b10d79 100644 --- a/app/src/main/java/io/legado/app/utils/compress/RarUtils.kt +++ b/app/src/main/java/io/legado/app/utils/compress/RarUtils.kt @@ -11,60 +11,65 @@ import java.io.InputStream object RarUtils { @Throws(NullPointerException::class, SecurityException::class) - fun unRarToPath(inputStream: InputStream, path: String): List { - return unRarToPath(inputStream, File(path)) + fun unRarToPath(inputStream: InputStream, path: String, filter: ((String) -> Boolean)? = null): List { + return unRarToPath(inputStream, File(path), filter) } @Throws(NullPointerException::class, SecurityException::class) - fun unRarToPath(byteArray: ByteArray, path: String): List { - return unRarToPath(byteArray, File(path)) + fun unRarToPath(byteArray: ByteArray, path: String, filter: ((String) -> Boolean)? = null): List { + return unRarToPath(byteArray, File(path), filter) } @Throws(NullPointerException::class, SecurityException::class) - fun unRarToPath(zipPath: String, path: String): List { - return unRarToPath(zipPath, File(path)) + fun unRarToPath(zipPath: String, path: String, filter: ((String) -> Boolean)? = null): List { + return unRarToPath(zipPath, File(path), filter) } @Throws(NullPointerException::class, SecurityException::class) - fun unRarToPath(file: File, path: String): List { - return unRarToPath(file, File(path)) + fun unRarToPath(file: File, path: String, filter: ((String) -> Boolean)? = null): List { + return unRarToPath(file, File(path), filter) } @Throws(NullPointerException::class, SecurityException::class) - fun unRarToPath(inputStream: InputStream, destDir: File?): List { + fun unRarToPath(inputStream: InputStream, destDir: File?, filter: ((String) -> Boolean)? = null): List { return Archive(inputStream).use { - unRarToPath(it, destDir) + unRarToPath(it, destDir, filter) } } @Throws(NullPointerException::class, SecurityException::class) - fun unRarToPath(byteArray: ByteArray, destDir: File?): List { + fun unRarToPath(byteArray: ByteArray, destDir: File?, filter: ((String) -> Boolean)? = null): List { return Archive(ByteArrayInputStream(byteArray)).use { - unRarToPath(it, destDir) + unRarToPath(it, destDir, filter) } } @Throws(NullPointerException::class, SecurityException::class) - fun unRarToPath(filePath: String, destDir: File?): List { + fun unRarToPath(filePath: String, destDir: File?, filter: ((String) -> Boolean)? = null): List { return Archive(File(filePath)).use { - unRarToPath(it, destDir) + unRarToPath(it, destDir, filter) } } @Throws(NullPointerException::class, SecurityException::class) - fun unRarToPath(file: File, destDir: File?): List { + fun unRarToPath(file: File, destDir: File?, filter: ((String) -> Boolean)? = null): List { return Archive(file).use { - unRarToPath(it, destDir) + unRarToPath(it, destDir, filter) } } @Throws(NullPointerException::class, SecurityException::class) - private fun unRarToPath(archive: Archive, destDir: File?): List { + private fun unRarToPath( + archive: Archive, + destDir: File?, + filter: ((String) -> Boolean)? = null + ): List { destDir ?: throw NullPointerException("解决路径不能为空") val files = arrayListOf() var entry: FileHeader? while (archive.nextFileHeader().also { entry = it } != null) { - val entryFile = File(destDir, entry!!.fileName) + val entryName = entry!!.fileName + val entryFile = File(destDir, entryName) if (!entryFile.canonicalPath.startsWith(destDir.canonicalPath)) { throw SecurityException("压缩文件只能解压到指定路径") } @@ -77,6 +82,7 @@ object RarUtils { if (entryFile.parentFile?.exists() != true) { entryFile.parentFile?.mkdirs() } + if (filter != null && !filter.invoke(entryName)) continue if (!entryFile.exists()) { entryFile.createNewFile() entryFile.setReadable(true) @@ -90,4 +96,32 @@ object RarUtils { return files } + + /* 遍历目录获取所有文件名 */ + @Throws(NullPointerException::class, SecurityException::class) + fun getFilesName( + inputStream: InputStream, + filter: ((String) -> Boolean)? = null + ): List { + return Archive(inputStream).use { + getFilesName(it, filter) + } + } + + @Throws(NullPointerException::class, SecurityException::class) + private fun getFilesName( + archive: Archive, + filter: ((String) -> Boolean)? = null + ): List { + val fileNames = mutableList() + var entry: FileHeader? + while (archive.nextFileHeader().also { entry = it } != null) { + if (entry!!.isDirectory) { + continue + } + fileNames.add(entry!!.fileName) + } + return fileNames + } + } \ No newline at end of file diff --git a/app/src/main/java/io/legado/app/utils/compress/SevenZipUtils.kt b/app/src/main/java/io/legado/app/utils/compress/SevenZipUtils.kt index 0d893d8b5..995de28d3 100644 --- a/app/src/main/java/io/legado/app/utils/compress/SevenZipUtils.kt +++ b/app/src/main/java/io/legado/app/utils/compress/SevenZipUtils.kt @@ -15,63 +15,64 @@ import java.nio.channels.FileChannel object SevenZipUtils { @Throws(NullPointerException::class, SecurityException::class) - fun un7zToPath(inputStream: InputStream, path: String): List { - return un7zToPath(inputStream, File(path)) + fun un7zToPath(inputStream: InputStream, path: String, filter: ((String) -> Boolean)? = null): List { + return un7zToPath(inputStream, File(path), filter) } @Throws(NullPointerException::class, SecurityException::class) - fun un7zToPath(byteArray: ByteArray, path: String): List { - return un7zToPath(byteArray, File(path)) + fun un7zToPath(byteArray: ByteArray, path: String, filter: ((String) -> Boolean)? = null): List { + return un7zToPath(byteArray, File(path),filter) } @Throws(NullPointerException::class, SecurityException::class) - fun un7zToPath(pfd: ParcelFileDescriptor, path: String): List { - return un7zToPath(pfd, File(path)) + fun un7zToPath(pfd: ParcelFileDescriptor, path: String, filter: ((String) -> Boolean)? = null): List { + return un7zToPath(pfd, File(path), filter) } @Throws(NullPointerException::class, SecurityException::class) - fun un7zToPath(fileChannel: FileChannel, path: String): List { - return un7zToPath(fileChannel, File(path)) + fun un7zToPath(fileChannel: FileChannel, path: String, filter: ((String) -> Boolean)? = null): List { + return un7zToPath(fileChannel, File(path), filter) } @Throws(NullPointerException::class, SecurityException::class) - fun un7zToPath(inputStream: InputStream, destDir: File?): List { - return un7zToPath(SevenZFile(SeekableInMemoryByteChannel(inputStream.readBytes())), destDir) + fun un7zToPath(inputStream: InputStream, destDir: File?, filter: ((String) -> Boolean)? = null): List { + return un7zToPath(SevenZFile(SeekableInMemoryByteChannel(inputStream.readBytes())), destDir, filter) } @Throws(NullPointerException::class, SecurityException::class) - fun un7zToPath(byteArray: ByteArray, destDir: File?): List { - return un7zToPath(SevenZFile(SeekableInMemoryByteChannel(byteArray)), destDir) + fun un7zToPath(byteArray: ByteArray, destDir: File?, filter: ((String) -> Boolean)? = null): List { + return un7zToPath(SevenZFile(SeekableInMemoryByteChannel(byteArray)), destDir, filter) } @Throws(NullPointerException::class, SecurityException::class) - fun un7zToPath(pfd: ParcelFileDescriptor, destDir: File?): List { - return un7zToPath(SevenZFile(ParcelFileDescriptorChannel(pfd)), destDir) + fun un7zToPath(pfd: ParcelFileDescriptor, destDir: File?, filter: ((String) -> Boolean)? = null): List { + return un7zToPath(SevenZFile(ParcelFileDescriptorChannel(pfd)), destDir, filter) } @SuppressLint("NewApi") @Throws(NullPointerException::class, SecurityException::class) - fun un7zToPath(fileChannel: FileChannel, destDir: File?): List { - return un7zToPath(SevenZFile(fileChannel), destDir) + fun un7zToPath(fileChannel: FileChannel, destDir: File?, filter: ((String) -> Boolean)? = null): List { + return un7zToPath(SevenZFile(fileChannel), destDir, filter) } @Throws(NullPointerException::class, SecurityException::class) - fun un7zToPath(file: File, destDir: File?): List { - return un7zToPath(SevenZFile(file), destDir) + fun un7zToPath(file: File, destDir: File?, filter: ((String) -> Boolean)? = null): List { + return un7zToPath(SevenZFile(file), destDir, filter) } @Throws(NullPointerException::class, SecurityException::class) - fun un7zToPath(filePath: String, destDir: File?): List { - return un7zToPath(SevenZFile(File(filePath)), destDir) + fun un7zToPath(filePath: String, destDir: File?, filter: ((String) -> Boolean)? = null): List { + return un7zToPath(SevenZFile(File(filePath)), destDir, filter) } @Throws(NullPointerException::class, SecurityException::class) - private fun un7zToPath(sevenZFile: SevenZFile, destDir: File?): List { + private fun un7zToPath(sevenZFile: SevenZFile, destDir: File?, filter: ((String) -> Boolean)? = null): List { destDir ?: throw NullPointerException("解决路径不能为空") val files = arrayListOf() var entry: SevenZArchiveEntry? while (sevenZFile.nextEntry.also { entry = it } != null) { - val entryFile = File(destDir, entry!!.name) + val entryName = entry!!.name + val entryFile = File(destDir, entryName) if (!entryFile.canonicalPath.startsWith(destDir.canonicalPath)) { throw SecurityException("压缩文件只能解压到指定路径") } @@ -84,6 +85,7 @@ object SevenZipUtils { if (entryFile.parentFile?.exists() != true) { entryFile.parentFile?.mkdirs() } + if (filter != null && !filter.invoke(entryName)) continue if (!entryFile.exists()) { entryFile.createNewFile() entryFile.setReadable(true) @@ -96,4 +98,34 @@ object SevenZipUtils { } return files } + + /* 遍历目录获取所有文件名 */ + @Throws(NullPointerException::class, SecurityException::class) + fun getFilesName( + inputStream: InputStream, + filter: ((String) -> Boolean)? = null + ): List { + return getFilesName( + SevenZFile(SeekableInMemoryByteChannel(inputStream.readBytes())), + filter + ) + } + + @Throws(NullPointerException::class, SecurityException::class) + private fun getFilesName( + sevenZFile: SevenZFile, + filter: ((String) -> Boolean)? = null + ): List { + val fileNames = mutableList() + var entry: SevenZArchiveEntry? + while (sevenZFile.nextEntry.also { entry = it } != null) { + if (entry!!.isDirectory) { + continue + } + fileNames.add(entry!!.name) + } + return fileNames + } + + } \ No newline at end of file diff --git a/app/src/main/java/io/legado/app/utils/compress/ZipUtils.kt b/app/src/main/java/io/legado/app/utils/compress/ZipUtils.kt index 87932a47d..c51d98876 100644 --- a/app/src/main/java/io/legado/app/utils/compress/ZipUtils.kt +++ b/app/src/main/java/io/legado/app/utils/compress/ZipUtils.kt @@ -179,39 +179,44 @@ object ZipUtils { } @Throws(SecurityException::class) - fun unZipToPath(file: File, path: String): List { + fun unZipToPath(file: File, path: String, filter: ((String) -> Boolean)? = null): List { return FileInputStream(file).use { - unZipToPath(it, path) + unZipToPath(it, path, filter) } } @Throws(SecurityException::class) - fun unZipToPath(file: File, dir: File): List { + fun unZipToPath(file: File, dir: File, filter: ((String) -> Boolean)? = null): List { return FileInputStream(file).use { - unZipToPath(it, dir) + unZipToPath(it, dir, filter) } } @Throws(SecurityException::class) - fun unZipToPath(inputStream: InputStream, path: String): List { + fun unZipToPath(inputStream: InputStream, path: String, filter: ((String) -> Boolean)? = null): List { return ZipArchiveInputStream(inputStream).use { - unZipToPath(it, File(path)) + unZipToPath(it, File(path), filter) } } @Throws(SecurityException::class) - fun unZipToPath(inputStream: InputStream, dir: File): List { + fun unZipToPath(inputStream: InputStream, dir: File, filter: ((String) -> Boolean)? = null): List { return ZipArchiveInputStream(inputStream).use { - unZipToPath(it, dir) + unZipToPath(it, dir, filter) } } @Throws(SecurityException::class) - private fun unZipToPath(zipInputStream: ZipArchiveInputStream, dir: File): List { + private fun unZipToPath( + zipInputStream: ZipArchiveInputStream, + dir: File, + filter: ((String) -> Boolean)? = null + ): List { val files = arrayListOf() var entry: ArchiveEntry? while (zipInputStream.nextEntry.also { entry = it } != null) { - val entryFile = File(dir, entry!!.name) + val entryName = entry!!.name + val entryFile = File(dir, entryName) if (!entryFile.canonicalPath.startsWith(dir.canonicalPath)) { throw SecurityException("压缩文件只能解压到指定路径") } @@ -224,6 +229,7 @@ object ZipUtils { if (entryFile.parentFile?.exists() != true) { entryFile.parentFile?.mkdirs() } + if (filter != null && !filter.invoke(entryName)) continue if (!entryFile.exists()) { entryFile.createNewFile() entryFile.setReadable(true) @@ -237,6 +243,32 @@ object ZipUtils { return files } + /* 遍历目录获取所有文件名 */ + @Throws(SecurityException::class) + fun getFilesName( + inputStream: InputStream, + filter: ((String) -> Boolean)? = null + ): List { + return ZipArchiveInputStream(inputStream).use { + getFilesName(it, filter) + } + } + + @Throws(SecurityException::class) + private fun getFilesName( + zipInputStream: ZipArchiveInputStream, + filter: ((String) -> Boolean)? = null + ): List { + val fileNames = mutableList() + var entry: ArchiveEntry? + while (zipInputStream.nextEntry.also { entry = it } != null) { + if (entry!!.isDirectory) { + continue + } + fileNames.add(entry!!.name) + } + return fileNames + } /** * Return the files' path in ZIP file.