mirror of
https://github.com/gedoor/legado.git
synced 2024-09-01 09:34:25 +08:00
Localbook实现导入压缩文件
This commit is contained in:
parent
64b93d0abb
commit
b9f86cbb14
2
.github/workflows/test.yml
vendored
2
.github/workflows/test.yml
vendored
@ -2,8 +2,6 @@ name: Test Build
|
|||||||
|
|
||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
branches:
|
|
||||||
- master
|
|
||||||
paths:
|
paths:
|
||||||
- '**'
|
- '**'
|
||||||
- '!**/assets/**'
|
- '!**/assets/**'
|
||||||
|
@ -6,6 +6,7 @@ import androidx.documentfile.provider.DocumentFile
|
|||||||
import com.script.SimpleBindings
|
import com.script.SimpleBindings
|
||||||
import io.legado.app.R
|
import io.legado.app.R
|
||||||
import io.legado.app.constant.AppConst
|
import io.legado.app.constant.AppConst
|
||||||
|
import io.legado.app.constant.AppPattern
|
||||||
import io.legado.app.constant.AppLog
|
import io.legado.app.constant.AppLog
|
||||||
import io.legado.app.constant.BookType
|
import io.legado.app.constant.BookType
|
||||||
import io.legado.app.data.appDb
|
import io.legado.app.data.appDb
|
||||||
@ -31,7 +32,7 @@ import java.util.regex.Pattern
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* 书籍文件导入 目录正文解析
|
* 书籍文件导入 目录正文解析
|
||||||
* 支持在线文件(txt epub umd 压缩文件需要用户解压) 本地文件
|
* 支持在线文件(txt epub umd 压缩文件 本地文件
|
||||||
*/
|
*/
|
||||||
object LocalBook {
|
object LocalBook {
|
||||||
|
|
||||||
@ -143,7 +144,6 @@ object LocalBook {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* 下载在线的文件并自动导入到阅读(txt umd epub)
|
* 下载在线的文件并自动导入到阅读(txt umd epub)
|
||||||
* 压缩文件请先提示用户解压
|
|
||||||
*/
|
*/
|
||||||
fun importFileOnLine(
|
fun importFileOnLine(
|
||||||
str: String,
|
str: String,
|
||||||
@ -188,6 +188,23 @@ object LocalBook {
|
|||||||
return book
|
return book
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun importArchiveFile(
|
||||||
|
uri: Uri,
|
||||||
|
saveFileName: String,
|
||||||
|
filter: ((String) -> Boolean)? = null
|
||||||
|
): List<Book> {
|
||||||
|
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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 从文件分析书籍必要信息(书名 作者等)
|
* 从文件分析书籍必要信息(书名 作者等)
|
||||||
*/
|
*/
|
||||||
|
@ -534,13 +534,13 @@ class BookInfoActivity :
|
|||||||
} else if (webFile.isSupportDecompress) {
|
} else if (webFile.isSupportDecompress) {
|
||||||
/* 解压筛选后再选择导入项 */
|
/* 解压筛选后再选择导入项 */
|
||||||
viewModel.importOrDownloadWebFile<Uri>(webFile) { uri ->
|
viewModel.importOrDownloadWebFile<Uri>(webFile) { uri ->
|
||||||
viewModel.deCompress(uri) { files ->
|
viewModel.getArchiveEntriesName(uri) { fileNames ->
|
||||||
if (files.size == 1) {
|
if (fileNames.size == 1) {
|
||||||
viewModel.importBook(files[0]) {
|
viewModel.importArchiveBook(uri, fileNames[0]) {
|
||||||
onClick?.invoke(it)
|
onClick?.invoke(it)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
showDecompressFileImportAlert(files, onClick)
|
showDecompressFileImportAlert(uri, fileNames, onClick)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -562,19 +562,19 @@ class BookInfoActivity :
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun showDecompressFileImportAlert(
|
private fun showDecompressFileImportAlert(
|
||||||
files: List<File>,
|
archiveFileUri: Uri,
|
||||||
|
fileNames: List<String>,
|
||||||
success: ((Book) -> Unit)? = null
|
success: ((Book) -> Unit)? = null
|
||||||
) {
|
) {
|
||||||
if (files.isEmpty()) {
|
if (fileNames.isEmpty()) {
|
||||||
toastOnUi(R.string.unsupport_archivefile_entry)
|
toastOnUi(R.string.unsupport_archivefile_entry)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
val selectorNames = files.map { it.name }
|
|
||||||
selector(
|
selector(
|
||||||
R.string.import_select_book,
|
R.string.import_select_book,
|
||||||
selectorNames
|
fileNames
|
||||||
) { _, _, index ->
|
) { _, name, _ ->
|
||||||
viewModel.importBook(files[index]) {
|
viewModel.importArchiveBook(archiveFileUri, name) {
|
||||||
success?.invoke(it)
|
success?.invoke(it)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -289,17 +289,17 @@ class BookInfoViewModel(application: Application) : BaseViewModel(application) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun deCompress(archiveFileUri: Uri, onSuccess: (List<File>) -> Unit) {
|
fun getArchiveEntriesName(archiveFileUri: Uri, onSuccess: (List<String>) -> Unit) {
|
||||||
execute {
|
execute {
|
||||||
ArchiveUtils.deCompress(archiveFileUri).filter {
|
ArchiveUtils.getArchiveFilesName(archiveFileUri) {
|
||||||
AppPattern.bookFileRegex.matches(it.name)
|
AppPattern.bookFileRegex.matches(it)
|
||||||
}
|
}
|
||||||
}.onError {
|
}.onError {
|
||||||
when (it) {
|
when (it) {
|
||||||
is UnsupportedRarV5Exception -> context.toastOnUi("暂不支持 rar v5 解压")
|
is UnsupportedRarV5Exception -> context.toastOnUi("暂不支持 rar v5 解压")
|
||||||
else -> {
|
else -> {
|
||||||
AppLog.put("DeCompress Error:\n${it.localizedMessage}", it)
|
AppLog.put("getArchiveEntriesName Error:\n${it.localizedMessage}", it)
|
||||||
context.toastOnUi("DeCompress Error:\n${it.localizedMessage}")
|
context.toastOnUi("getArchiveEntriesName Error:\n${it.localizedMessage}")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}.onSuccess {
|
}.onSuccess {
|
||||||
@ -308,19 +308,25 @@ class BookInfoViewModel(application: Application) : BaseViewModel(application) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Suppress("BlockingMethodInNonBlockingContext")
|
@Suppress("BlockingMethodInNonBlockingContext")
|
||||||
fun importBook(file: File, success: ((Book) -> Unit)? = null) {
|
fun importArchiveBook(
|
||||||
|
archiveFileUri: Uri,
|
||||||
|
archiveEntryName: String,
|
||||||
|
success: ((Book) -> Unit)? = null
|
||||||
|
) {
|
||||||
execute {
|
execute {
|
||||||
val suffix = file.name.substringAfterLast(".")
|
val suffix = archiveEntryName.substringAfterLast(".")
|
||||||
LocalBook.saveBookFile(
|
LocalBook.importArchiveFile(
|
||||||
FileInputStream(file),
|
archiveFileUri,
|
||||||
bookData.value!!.getExportFileName(suffix)
|
bookData.value!!.getExportFileName(suffix)
|
||||||
)
|
) {
|
||||||
|
it.contains(archiveEntryName)
|
||||||
|
}.first()
|
||||||
}.onSuccess {
|
}.onSuccess {
|
||||||
val book = changeToLocalBook(LocalBook.importFile(it))
|
val book = changeToLocalBook(it)
|
||||||
success?.invoke(book)
|
success?.invoke(book)
|
||||||
}.onError {
|
}.onError {
|
||||||
AppLog.put("ImportBook Error:\n${it.localizedMessage}", it)
|
AppLog.put("importArchiveBook Error:\n${it.localizedMessage}", it)
|
||||||
context.toastOnUi("ImportBook Error:\n${it.localizedMessage}")
|
context.toastOnUi("importArchiveBook Error:\n${it.localizedMessage}")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -20,50 +20,96 @@ object ArchiveUtils {
|
|||||||
|
|
||||||
fun deCompress(
|
fun deCompress(
|
||||||
archiveUri: Uri,
|
archiveUri: Uri,
|
||||||
path: String = TEMP_PATH
|
path: String = TEMP_PATH,
|
||||||
|
filter: ((String) -> Boolean)? = null
|
||||||
): List<File> {
|
): List<File> {
|
||||||
return deCompress(FileDoc.fromUri(archiveUri, false), path)
|
return deCompress(FileDoc.fromUri(archiveUri, false), path, filter)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun deCompress(
|
fun deCompress(
|
||||||
archivePath: String,
|
archivePath: String,
|
||||||
path: String = TEMP_PATH
|
path: String = TEMP_PATH,
|
||||||
|
filter: ((String) -> Boolean)? = null
|
||||||
): List<File> {
|
): List<File> {
|
||||||
return deCompress(Uri.parse(archivePath), path)
|
return deCompress(Uri.parse(archivePath), path, filter)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun deCompress(
|
fun deCompress(
|
||||||
archiveFile: File,
|
archiveFile: File,
|
||||||
path: String = TEMP_PATH
|
path: String = TEMP_PATH,
|
||||||
|
filter: ((String) -> Boolean)? = null
|
||||||
): List<File> {
|
): List<File> {
|
||||||
return deCompress(FileDoc.fromFile(archiveFile), path)
|
return deCompress(FileDoc.fromFile(archiveFile), path, filter)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun deCompress(
|
fun deCompress(
|
||||||
archiveDoc: DocumentFile,
|
archiveDoc: DocumentFile,
|
||||||
path: String = TEMP_PATH
|
path: String = TEMP_PATH,
|
||||||
|
filter: ((String) -> Boolean)? = null
|
||||||
): List<File> {
|
): List<File> {
|
||||||
return deCompress(FileDoc.fromDocumentFile(archiveDoc), path)
|
return deCompress(FileDoc.fromDocumentFile(archiveDoc), path, filter)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun deCompress(
|
fun deCompress(
|
||||||
archiveFileDoc: FileDoc,
|
archiveFileDoc: FileDoc,
|
||||||
path: String = TEMP_PATH
|
path: String = TEMP_PATH,
|
||||||
|
filter: ((String) -> Boolean)? = null
|
||||||
): List<File> {
|
): List<File> {
|
||||||
if (archiveFileDoc.isDir) throw IllegalArgumentException("Unexpected Folder input")
|
if (archiveFileDoc.isDir) throw IllegalArgumentException("Unexpected Folder input")
|
||||||
val name = archiveFileDoc.name
|
val name = archiveFileDoc.name
|
||||||
|
checkAchieve(name)
|
||||||
val workPathFileDoc = getCacheFolderFileDoc(name, path)
|
val workPathFileDoc = getCacheFolderFileDoc(name, path)
|
||||||
val workPath = workPathFileDoc.toString()
|
val workPath = workPathFileDoc.toString()
|
||||||
return archiveFileDoc.openInputStream().getOrThrow().use {
|
return archiveFileDoc.openInputStream().getOrThrow().use {
|
||||||
when {
|
when {
|
||||||
name.endsWith(".zip", ignoreCase = true) -> ZipUtils.unZipToPath(it, workPath)
|
name.endsWith(".zip", ignoreCase = true) -> ZipUtils.unZipToPath(it, workPath, filter)
|
||||||
name.endsWith(".rar", ignoreCase = true) -> RarUtils.unRarToPath(it, workPath)
|
name.endsWith(".rar", ignoreCase = true) -> RarUtils.unRarToPath(it, workPath, filter)
|
||||||
name.endsWith(".7z", ignoreCase = true) -> SevenZipUtils.un7zToPath(it, workPath)
|
name.endsWith(".7z", ignoreCase = true) -> SevenZipUtils.un7zToPath(it, workPath, filter)
|
||||||
else -> throw IllegalArgumentException("Unexpected archive format")
|
else -> throw IllegalArgumentException("Unexpected archive format")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* 遍历目录获取文件名 */
|
||||||
|
fun getArchiveFilesName(fileUri: Uri, filter: ((String) -> Boolean)? = null): List<String> = getArchiveEntriesName(FileDoc.fromUri(fileUri, false), filter)
|
||||||
|
|
||||||
|
fun getArchiveFilesName(
|
||||||
|
fileDoc: FileDoc,
|
||||||
|
filter: ((String) -> Boolean)? = null
|
||||||
|
): List<String> {
|
||||||
|
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(
|
private fun getCacheFolderFileDoc(
|
||||||
archiveName: String,
|
archiveName: String,
|
||||||
workPath: String
|
workPath: String
|
||||||
|
@ -11,60 +11,65 @@ import java.io.InputStream
|
|||||||
object RarUtils {
|
object RarUtils {
|
||||||
|
|
||||||
@Throws(NullPointerException::class, SecurityException::class)
|
@Throws(NullPointerException::class, SecurityException::class)
|
||||||
fun unRarToPath(inputStream: InputStream, path: String): List<File> {
|
fun unRarToPath(inputStream: InputStream, path: String, filter: ((String) -> Boolean)? = null): List<File> {
|
||||||
return unRarToPath(inputStream, File(path))
|
return unRarToPath(inputStream, File(path), filter)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Throws(NullPointerException::class, SecurityException::class)
|
@Throws(NullPointerException::class, SecurityException::class)
|
||||||
fun unRarToPath(byteArray: ByteArray, path: String): List<File> {
|
fun unRarToPath(byteArray: ByteArray, path: String, filter: ((String) -> Boolean)? = null): List<File> {
|
||||||
return unRarToPath(byteArray, File(path))
|
return unRarToPath(byteArray, File(path), filter)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Throws(NullPointerException::class, SecurityException::class)
|
@Throws(NullPointerException::class, SecurityException::class)
|
||||||
fun unRarToPath(zipPath: String, path: String): List<File> {
|
fun unRarToPath(zipPath: String, path: String, filter: ((String) -> Boolean)? = null): List<File> {
|
||||||
return unRarToPath(zipPath, File(path))
|
return unRarToPath(zipPath, File(path), filter)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Throws(NullPointerException::class, SecurityException::class)
|
@Throws(NullPointerException::class, SecurityException::class)
|
||||||
fun unRarToPath(file: File, path: String): List<File> {
|
fun unRarToPath(file: File, path: String, filter: ((String) -> Boolean)? = null): List<File> {
|
||||||
return unRarToPath(file, File(path))
|
return unRarToPath(file, File(path), filter)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Throws(NullPointerException::class, SecurityException::class)
|
@Throws(NullPointerException::class, SecurityException::class)
|
||||||
fun unRarToPath(inputStream: InputStream, destDir: File?): List<File> {
|
fun unRarToPath(inputStream: InputStream, destDir: File?, filter: ((String) -> Boolean)? = null): List<File> {
|
||||||
return Archive(inputStream).use {
|
return Archive(inputStream).use {
|
||||||
unRarToPath(it, destDir)
|
unRarToPath(it, destDir, filter)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Throws(NullPointerException::class, SecurityException::class)
|
@Throws(NullPointerException::class, SecurityException::class)
|
||||||
fun unRarToPath(byteArray: ByteArray, destDir: File?): List<File> {
|
fun unRarToPath(byteArray: ByteArray, destDir: File?, filter: ((String) -> Boolean)? = null): List<File> {
|
||||||
return Archive(ByteArrayInputStream(byteArray)).use {
|
return Archive(ByteArrayInputStream(byteArray)).use {
|
||||||
unRarToPath(it, destDir)
|
unRarToPath(it, destDir, filter)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Throws(NullPointerException::class, SecurityException::class)
|
@Throws(NullPointerException::class, SecurityException::class)
|
||||||
fun unRarToPath(filePath: String, destDir: File?): List<File> {
|
fun unRarToPath(filePath: String, destDir: File?, filter: ((String) -> Boolean)? = null): List<File> {
|
||||||
return Archive(File(filePath)).use {
|
return Archive(File(filePath)).use {
|
||||||
unRarToPath(it, destDir)
|
unRarToPath(it, destDir, filter)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Throws(NullPointerException::class, SecurityException::class)
|
@Throws(NullPointerException::class, SecurityException::class)
|
||||||
fun unRarToPath(file: File, destDir: File?): List<File> {
|
fun unRarToPath(file: File, destDir: File?, filter: ((String) -> Boolean)? = null): List<File> {
|
||||||
return Archive(file).use {
|
return Archive(file).use {
|
||||||
unRarToPath(it, destDir)
|
unRarToPath(it, destDir, filter)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Throws(NullPointerException::class, SecurityException::class)
|
@Throws(NullPointerException::class, SecurityException::class)
|
||||||
private fun unRarToPath(archive: Archive, destDir: File?): List<File> {
|
private fun unRarToPath(
|
||||||
|
archive: Archive,
|
||||||
|
destDir: File?,
|
||||||
|
filter: ((String) -> Boolean)? = null
|
||||||
|
): List<File> {
|
||||||
destDir ?: throw NullPointerException("解决路径不能为空")
|
destDir ?: throw NullPointerException("解决路径不能为空")
|
||||||
val files = arrayListOf<File>()
|
val files = arrayListOf<File>()
|
||||||
var entry: FileHeader?
|
var entry: FileHeader?
|
||||||
while (archive.nextFileHeader().also { entry = it } != null) {
|
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)) {
|
if (!entryFile.canonicalPath.startsWith(destDir.canonicalPath)) {
|
||||||
throw SecurityException("压缩文件只能解压到指定路径")
|
throw SecurityException("压缩文件只能解压到指定路径")
|
||||||
}
|
}
|
||||||
@ -77,6 +82,7 @@ object RarUtils {
|
|||||||
if (entryFile.parentFile?.exists() != true) {
|
if (entryFile.parentFile?.exists() != true) {
|
||||||
entryFile.parentFile?.mkdirs()
|
entryFile.parentFile?.mkdirs()
|
||||||
}
|
}
|
||||||
|
if (filter != null && !filter.invoke(entryName)) continue
|
||||||
if (!entryFile.exists()) {
|
if (!entryFile.exists()) {
|
||||||
entryFile.createNewFile()
|
entryFile.createNewFile()
|
||||||
entryFile.setReadable(true)
|
entryFile.setReadable(true)
|
||||||
@ -90,4 +96,32 @@ object RarUtils {
|
|||||||
return files
|
return files
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* 遍历目录获取所有文件名 */
|
||||||
|
@Throws(NullPointerException::class, SecurityException::class)
|
||||||
|
fun getFilesName(
|
||||||
|
inputStream: InputStream,
|
||||||
|
filter: ((String) -> Boolean)? = null
|
||||||
|
): List<String> {
|
||||||
|
return Archive(inputStream).use {
|
||||||
|
getFilesName(it, filter)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Throws(NullPointerException::class, SecurityException::class)
|
||||||
|
private fun getFilesName(
|
||||||
|
archive: Archive,
|
||||||
|
filter: ((String) -> Boolean)? = null
|
||||||
|
): List<String> {
|
||||||
|
val fileNames = mutableList<String>()
|
||||||
|
var entry: FileHeader?
|
||||||
|
while (archive.nextFileHeader().also { entry = it } != null) {
|
||||||
|
if (entry!!.isDirectory) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
fileNames.add(entry!!.fileName)
|
||||||
|
}
|
||||||
|
return fileNames
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -15,63 +15,64 @@ import java.nio.channels.FileChannel
|
|||||||
object SevenZipUtils {
|
object SevenZipUtils {
|
||||||
|
|
||||||
@Throws(NullPointerException::class, SecurityException::class)
|
@Throws(NullPointerException::class, SecurityException::class)
|
||||||
fun un7zToPath(inputStream: InputStream, path: String): List<File> {
|
fun un7zToPath(inputStream: InputStream, path: String, filter: ((String) -> Boolean)? = null): List<File> {
|
||||||
return un7zToPath(inputStream, File(path))
|
return un7zToPath(inputStream, File(path), filter)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Throws(NullPointerException::class, SecurityException::class)
|
@Throws(NullPointerException::class, SecurityException::class)
|
||||||
fun un7zToPath(byteArray: ByteArray, path: String): List<File> {
|
fun un7zToPath(byteArray: ByteArray, path: String, filter: ((String) -> Boolean)? = null): List<File> {
|
||||||
return un7zToPath(byteArray, File(path))
|
return un7zToPath(byteArray, File(path),filter)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Throws(NullPointerException::class, SecurityException::class)
|
@Throws(NullPointerException::class, SecurityException::class)
|
||||||
fun un7zToPath(pfd: ParcelFileDescriptor, path: String): List<File> {
|
fun un7zToPath(pfd: ParcelFileDescriptor, path: String, filter: ((String) -> Boolean)? = null): List<File> {
|
||||||
return un7zToPath(pfd, File(path))
|
return un7zToPath(pfd, File(path), filter)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Throws(NullPointerException::class, SecurityException::class)
|
@Throws(NullPointerException::class, SecurityException::class)
|
||||||
fun un7zToPath(fileChannel: FileChannel, path: String): List<File> {
|
fun un7zToPath(fileChannel: FileChannel, path: String, filter: ((String) -> Boolean)? = null): List<File> {
|
||||||
return un7zToPath(fileChannel, File(path))
|
return un7zToPath(fileChannel, File(path), filter)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Throws(NullPointerException::class, SecurityException::class)
|
@Throws(NullPointerException::class, SecurityException::class)
|
||||||
fun un7zToPath(inputStream: InputStream, destDir: File?): List<File> {
|
fun un7zToPath(inputStream: InputStream, destDir: File?, filter: ((String) -> Boolean)? = null): List<File> {
|
||||||
return un7zToPath(SevenZFile(SeekableInMemoryByteChannel(inputStream.readBytes())), destDir)
|
return un7zToPath(SevenZFile(SeekableInMemoryByteChannel(inputStream.readBytes())), destDir, filter)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Throws(NullPointerException::class, SecurityException::class)
|
@Throws(NullPointerException::class, SecurityException::class)
|
||||||
fun un7zToPath(byteArray: ByteArray, destDir: File?): List<File> {
|
fun un7zToPath(byteArray: ByteArray, destDir: File?, filter: ((String) -> Boolean)? = null): List<File> {
|
||||||
return un7zToPath(SevenZFile(SeekableInMemoryByteChannel(byteArray)), destDir)
|
return un7zToPath(SevenZFile(SeekableInMemoryByteChannel(byteArray)), destDir, filter)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Throws(NullPointerException::class, SecurityException::class)
|
@Throws(NullPointerException::class, SecurityException::class)
|
||||||
fun un7zToPath(pfd: ParcelFileDescriptor, destDir: File?): List<File> {
|
fun un7zToPath(pfd: ParcelFileDescriptor, destDir: File?, filter: ((String) -> Boolean)? = null): List<File> {
|
||||||
return un7zToPath(SevenZFile(ParcelFileDescriptorChannel(pfd)), destDir)
|
return un7zToPath(SevenZFile(ParcelFileDescriptorChannel(pfd)), destDir, filter)
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressLint("NewApi")
|
@SuppressLint("NewApi")
|
||||||
@Throws(NullPointerException::class, SecurityException::class)
|
@Throws(NullPointerException::class, SecurityException::class)
|
||||||
fun un7zToPath(fileChannel: FileChannel, destDir: File?): List<File> {
|
fun un7zToPath(fileChannel: FileChannel, destDir: File?, filter: ((String) -> Boolean)? = null): List<File> {
|
||||||
return un7zToPath(SevenZFile(fileChannel), destDir)
|
return un7zToPath(SevenZFile(fileChannel), destDir, filter)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Throws(NullPointerException::class, SecurityException::class)
|
@Throws(NullPointerException::class, SecurityException::class)
|
||||||
fun un7zToPath(file: File, destDir: File?): List<File> {
|
fun un7zToPath(file: File, destDir: File?, filter: ((String) -> Boolean)? = null): List<File> {
|
||||||
return un7zToPath(SevenZFile(file), destDir)
|
return un7zToPath(SevenZFile(file), destDir, filter)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Throws(NullPointerException::class, SecurityException::class)
|
@Throws(NullPointerException::class, SecurityException::class)
|
||||||
fun un7zToPath(filePath: String, destDir: File?): List<File> {
|
fun un7zToPath(filePath: String, destDir: File?, filter: ((String) -> Boolean)? = null): List<File> {
|
||||||
return un7zToPath(SevenZFile(File(filePath)), destDir)
|
return un7zToPath(SevenZFile(File(filePath)), destDir, filter)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Throws(NullPointerException::class, SecurityException::class)
|
@Throws(NullPointerException::class, SecurityException::class)
|
||||||
private fun un7zToPath(sevenZFile: SevenZFile, destDir: File?): List<File> {
|
private fun un7zToPath(sevenZFile: SevenZFile, destDir: File?, filter: ((String) -> Boolean)? = null): List<File> {
|
||||||
destDir ?: throw NullPointerException("解决路径不能为空")
|
destDir ?: throw NullPointerException("解决路径不能为空")
|
||||||
val files = arrayListOf<File>()
|
val files = arrayListOf<File>()
|
||||||
var entry: SevenZArchiveEntry?
|
var entry: SevenZArchiveEntry?
|
||||||
while (sevenZFile.nextEntry.also { entry = it } != null) {
|
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)) {
|
if (!entryFile.canonicalPath.startsWith(destDir.canonicalPath)) {
|
||||||
throw SecurityException("压缩文件只能解压到指定路径")
|
throw SecurityException("压缩文件只能解压到指定路径")
|
||||||
}
|
}
|
||||||
@ -84,6 +85,7 @@ object SevenZipUtils {
|
|||||||
if (entryFile.parentFile?.exists() != true) {
|
if (entryFile.parentFile?.exists() != true) {
|
||||||
entryFile.parentFile?.mkdirs()
|
entryFile.parentFile?.mkdirs()
|
||||||
}
|
}
|
||||||
|
if (filter != null && !filter.invoke(entryName)) continue
|
||||||
if (!entryFile.exists()) {
|
if (!entryFile.exists()) {
|
||||||
entryFile.createNewFile()
|
entryFile.createNewFile()
|
||||||
entryFile.setReadable(true)
|
entryFile.setReadable(true)
|
||||||
@ -96,4 +98,34 @@ object SevenZipUtils {
|
|||||||
}
|
}
|
||||||
return files
|
return files
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* 遍历目录获取所有文件名 */
|
||||||
|
@Throws(NullPointerException::class, SecurityException::class)
|
||||||
|
fun getFilesName(
|
||||||
|
inputStream: InputStream,
|
||||||
|
filter: ((String) -> Boolean)? = null
|
||||||
|
): List<String> {
|
||||||
|
return getFilesName(
|
||||||
|
SevenZFile(SeekableInMemoryByteChannel(inputStream.readBytes())),
|
||||||
|
filter
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Throws(NullPointerException::class, SecurityException::class)
|
||||||
|
private fun getFilesName(
|
||||||
|
sevenZFile: SevenZFile,
|
||||||
|
filter: ((String) -> Boolean)? = null
|
||||||
|
): List<String> {
|
||||||
|
val fileNames = mutableList<String>()
|
||||||
|
var entry: SevenZArchiveEntry?
|
||||||
|
while (sevenZFile.nextEntry.also { entry = it } != null) {
|
||||||
|
if (entry!!.isDirectory) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
fileNames.add(entry!!.name)
|
||||||
|
}
|
||||||
|
return fileNames
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
@ -179,39 +179,44 @@ object ZipUtils {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Throws(SecurityException::class)
|
@Throws(SecurityException::class)
|
||||||
fun unZipToPath(file: File, path: String): List<File> {
|
fun unZipToPath(file: File, path: String, filter: ((String) -> Boolean)? = null): List<File> {
|
||||||
return FileInputStream(file).use {
|
return FileInputStream(file).use {
|
||||||
unZipToPath(it, path)
|
unZipToPath(it, path, filter)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Throws(SecurityException::class)
|
@Throws(SecurityException::class)
|
||||||
fun unZipToPath(file: File, dir: File): List<File> {
|
fun unZipToPath(file: File, dir: File, filter: ((String) -> Boolean)? = null): List<File> {
|
||||||
return FileInputStream(file).use {
|
return FileInputStream(file).use {
|
||||||
unZipToPath(it, dir)
|
unZipToPath(it, dir, filter)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Throws(SecurityException::class)
|
@Throws(SecurityException::class)
|
||||||
fun unZipToPath(inputStream: InputStream, path: String): List<File> {
|
fun unZipToPath(inputStream: InputStream, path: String, filter: ((String) -> Boolean)? = null): List<File> {
|
||||||
return ZipArchiveInputStream(inputStream).use {
|
return ZipArchiveInputStream(inputStream).use {
|
||||||
unZipToPath(it, File(path))
|
unZipToPath(it, File(path), filter)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Throws(SecurityException::class)
|
@Throws(SecurityException::class)
|
||||||
fun unZipToPath(inputStream: InputStream, dir: File): List<File> {
|
fun unZipToPath(inputStream: InputStream, dir: File, filter: ((String) -> Boolean)? = null): List<File> {
|
||||||
return ZipArchiveInputStream(inputStream).use {
|
return ZipArchiveInputStream(inputStream).use {
|
||||||
unZipToPath(it, dir)
|
unZipToPath(it, dir, filter)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Throws(SecurityException::class)
|
@Throws(SecurityException::class)
|
||||||
private fun unZipToPath(zipInputStream: ZipArchiveInputStream, dir: File): List<File> {
|
private fun unZipToPath(
|
||||||
|
zipInputStream: ZipArchiveInputStream,
|
||||||
|
dir: File,
|
||||||
|
filter: ((String) -> Boolean)? = null
|
||||||
|
): List<File> {
|
||||||
val files = arrayListOf<File>()
|
val files = arrayListOf<File>()
|
||||||
var entry: ArchiveEntry?
|
var entry: ArchiveEntry?
|
||||||
while (zipInputStream.nextEntry.also { entry = it } != null) {
|
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)) {
|
if (!entryFile.canonicalPath.startsWith(dir.canonicalPath)) {
|
||||||
throw SecurityException("压缩文件只能解压到指定路径")
|
throw SecurityException("压缩文件只能解压到指定路径")
|
||||||
}
|
}
|
||||||
@ -224,6 +229,7 @@ object ZipUtils {
|
|||||||
if (entryFile.parentFile?.exists() != true) {
|
if (entryFile.parentFile?.exists() != true) {
|
||||||
entryFile.parentFile?.mkdirs()
|
entryFile.parentFile?.mkdirs()
|
||||||
}
|
}
|
||||||
|
if (filter != null && !filter.invoke(entryName)) continue
|
||||||
if (!entryFile.exists()) {
|
if (!entryFile.exists()) {
|
||||||
entryFile.createNewFile()
|
entryFile.createNewFile()
|
||||||
entryFile.setReadable(true)
|
entryFile.setReadable(true)
|
||||||
@ -237,6 +243,32 @@ object ZipUtils {
|
|||||||
return files
|
return files
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* 遍历目录获取所有文件名 */
|
||||||
|
@Throws(SecurityException::class)
|
||||||
|
fun getFilesName(
|
||||||
|
inputStream: InputStream,
|
||||||
|
filter: ((String) -> Boolean)? = null
|
||||||
|
): List<String> {
|
||||||
|
return ZipArchiveInputStream(inputStream).use {
|
||||||
|
getFilesName(it, filter)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Throws(SecurityException::class)
|
||||||
|
private fun getFilesName(
|
||||||
|
zipInputStream: ZipArchiveInputStream,
|
||||||
|
filter: ((String) -> Boolean)? = null
|
||||||
|
): List<String> {
|
||||||
|
val fileNames = mutableList<String>()
|
||||||
|
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.
|
* Return the files' path in ZIP file.
|
||||||
|
Loading…
Reference in New Issue
Block a user