mirror of
https://github.com/TermoraDev/termora.git
synced 2026-01-16 02:12:58 +08:00
chore: supports retaining file modification date
This commit is contained in:
@@ -1,12 +1,19 @@
|
|||||||
package app.termora.transfer
|
package app.termora.transfer
|
||||||
|
|
||||||
|
import app.termora.database.DatabaseManager
|
||||||
import org.apache.commons.io.IOUtils
|
import org.apache.commons.io.IOUtils
|
||||||
|
import org.apache.sshd.sftp.client.fs.SftpFileSystem
|
||||||
|
import org.apache.sshd.sftp.common.SftpConstants
|
||||||
|
import org.slf4j.LoggerFactory
|
||||||
import java.io.Closeable
|
import java.io.Closeable
|
||||||
import java.io.InputStream
|
import java.io.InputStream
|
||||||
import java.io.OutputStream
|
import java.io.OutputStream
|
||||||
|
import java.nio.file.Files
|
||||||
import java.nio.file.Path
|
import java.nio.file.Path
|
||||||
import java.nio.file.StandardOpenOption
|
import java.nio.file.StandardOpenOption
|
||||||
|
import java.nio.file.attribute.BasicFileAttributeView
|
||||||
import java.util.concurrent.atomic.AtomicBoolean
|
import java.util.concurrent.atomic.AtomicBoolean
|
||||||
|
import kotlin.io.path.getLastModifiedTime
|
||||||
import kotlin.io.path.inputStream
|
import kotlin.io.path.inputStream
|
||||||
import kotlin.io.path.outputStream
|
import kotlin.io.path.outputStream
|
||||||
|
|
||||||
@@ -15,10 +22,13 @@ class FileTransfer(
|
|||||||
private val action: TransferAction,
|
private val action: TransferAction,
|
||||||
priority: Transfer.Priority = Transfer.Priority.Normal,
|
priority: Transfer.Priority = Transfer.Priority.Normal,
|
||||||
) : AbstractTransfer(parentId, source, target, false, priority), Closeable {
|
) : AbstractTransfer(parentId, source, target, false, priority), Closeable {
|
||||||
|
companion object {
|
||||||
|
private val log = LoggerFactory.getLogger(FileTransfer::class.java)
|
||||||
|
}
|
||||||
|
|
||||||
private lateinit var input: InputStream
|
private lateinit var input: InputStream
|
||||||
private lateinit var output: OutputStream
|
private lateinit var output: OutputStream
|
||||||
|
private val isPreserveModificationTime get() = DatabaseManager.getInstance().sftp.preserveModificationTime
|
||||||
private val closed = AtomicBoolean(false)
|
private val closed = AtomicBoolean(false)
|
||||||
|
|
||||||
override suspend fun transfer(bufferSize: Int): Long {
|
override suspend fun transfer(bufferSize: Int): Long {
|
||||||
@@ -31,7 +41,7 @@ class FileTransfer(
|
|||||||
|
|
||||||
if (::output.isInitialized.not()) {
|
if (::output.isInitialized.not()) {
|
||||||
output = if (action == TransferAction.Overwrite) {
|
output = if (action == TransferAction.Overwrite) {
|
||||||
target().outputStream(StandardOpenOption.CREATE, StandardOpenOption.TRUNCATE_EXISTING)
|
target().outputStream()
|
||||||
} else {
|
} else {
|
||||||
target().outputStream(StandardOpenOption.WRITE, StandardOpenOption.APPEND)
|
target().outputStream(StandardOpenOption.WRITE, StandardOpenOption.APPEND)
|
||||||
}
|
}
|
||||||
@@ -40,6 +50,7 @@ class FileTransfer(
|
|||||||
val buffer = ByteArray(bufferSize)
|
val buffer = ByteArray(bufferSize)
|
||||||
val len = input.read(buffer)
|
val len = input.read(buffer)
|
||||||
if (len <= 0) return 0
|
if (len <= 0) return 0
|
||||||
|
|
||||||
output.write(buffer, 0, len)
|
output.write(buffer, 0, len)
|
||||||
return len.toLong()
|
return len.toLong()
|
||||||
}
|
}
|
||||||
@@ -61,6 +72,24 @@ class FileTransfer(
|
|||||||
if (::output.isInitialized) {
|
if (::output.isInitialized) {
|
||||||
IOUtils.closeQuietly(output)
|
IOUtils.closeQuietly(output)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (isPreserveModificationTime) {
|
||||||
|
runCatching {
|
||||||
|
val time = source().getLastModifiedTime()
|
||||||
|
val fs = target().fileSystem
|
||||||
|
// SFTP 比较特殊
|
||||||
|
if (fs is SftpFileSystem && fs.version == SftpConstants.SFTP_V3) {
|
||||||
|
val view = Files.getFileAttributeView(target(), BasicFileAttributeView::class.java)
|
||||||
|
view.setTimes(time, time, null)
|
||||||
|
} else {
|
||||||
|
Files.setLastModifiedTime(target(), time)
|
||||||
|
}
|
||||||
|
}.onFailure {
|
||||||
|
if (log.isWarnEnabled) {
|
||||||
|
log.error(it.message, it)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user