Skip to content

Commit

Permalink
✨ SFTP支持上传嵌套文件夹
Browse files Browse the repository at this point in the history
  • Loading branch information
chaos-zhu committed Aug 13, 2024
1 parent afda15d commit 9889528
Show file tree
Hide file tree
Showing 2 changed files with 40 additions and 28 deletions.
39 changes: 24 additions & 15 deletions server/app/socket/sftp.js
Original file line number Diff line number Diff line change
Expand Up @@ -55,10 +55,12 @@ function listenInput(sftpClient, socket) {
})
// socket.on('down_dir', async (path) => {
// const exists = await sftpClient.exists(path)
// if(!exists) return socket.emit('not_exists_dir', '文件夹不存在或当前不可访问')
// if(!exists) return socket.emit('not_exists_dir', '目录不存在或当前不可访问')
// let res = await sftpClient.downloadDir(path, sftpCacheDir)
// socket.emit('down_dir_success', res)
// })

// 下载
socket.on('down_file', async ({ path, name, size, target = 'down' }) => {
// target: down or preview
const exists = await sftpClient.exists(path)
Expand Down Expand Up @@ -94,10 +96,12 @@ function listenInput(sftpClient, socket) {
socket.emit('sftp_error', error.message)
}
})

// 上传
socket.on('up_file', async ({ targetPath, fullPath, name, file }) => {
// console.log({ targetPath, fullPath, name, file })
const exists = await sftpClient.exists(targetPath)
if(!exists) return socket.emit('not_exists_dir', '文件夹不存在或当前不可访问')
if(!exists) return socket.emit('not_exists_dir', '目录不存在或当前不可访问')
try {
const localPath = rawPath.join(sftpCacheDir, name)
fs.writeFileSync(localPath, file)
Expand All @@ -110,30 +114,35 @@ function listenInput(sftpClient, socket) {
}
})

// 上传文件夹先在目标sftp服务器创建文件夹
socket.on('create_remote_dir', async ({ targetDirPath, folderName }) => {
let fullPath = rawPath.posix.join(targetDirPath, folderName)
consola.info('创建远程服务器文件夹:', fullPath)
const exists = await sftpClient.exists(fullPath)
if(exists) return socket.emit('is_exists_dir', '上传文件夹失败,文件夹已存在')
let res = await sftpClient.mkdir(fullPath)
consola.success('创建远程服务器文件夹成功:', fullPath)
socket.emit('create_remote_dir_success', res)
// 上传目录先在目标sftp服务器创建目录
socket.on('create_remote_dir', async ({ targetDirPath, foldersName }) => {
let baseFolderPath = rawPath.posix.join(targetDirPath, foldersName[0].split('/')[0])
let baseFolderPathExists = await sftpClient.exists(baseFolderPath)
if (baseFolderPathExists) return socket.emit('create_remote_dir_exists', `远程目录已存在: ${ baseFolderPath }`)
consola.info('准备创建远程服务器目录:', foldersName)
for (const folderName of foldersName) {
const fullPath = rawPath.posix.join(targetDirPath, folderName)
const exists = await sftpClient.exists(fullPath)
if (exists) continue
await sftpClient.mkdir(fullPath, true)
consola.info('创建目录:', fullPath)
}
socket.emit('create_remote_dir_success')
})

/** 分片上传 */
// 1. 创建本地缓存文件夹
// 1. 创建本地缓存目录
let md5List = []
socket.on('create_cache_dir', async ({ targetDirPath, name }) => {
// console.log({ targetDirPath, name })
const exists = await sftpClient.exists(targetDirPath)
if(!exists) return socket.emit('not_exists_dir', '文件夹不存在或当前不可访问')
if(!exists) return socket.emit('not_exists_dir', '目录不存在或当前不可访问')
md5List = []
const localPath = rawPath.join(sftpCacheDir, name)
fs.emptyDirSync(localPath) // 不存在会创建,存在则清空
socket.emit('create_cache_success')
})
// 2. 上传分片
// 2. 上传分片到面板服务
socket.on('up_file_slice', async ({ name, sliceFile, fileIndex }) => {
// console.log('up_file_slice:', fileIndex, name)
try {
Expand All @@ -147,7 +156,7 @@ function listenInput(sftpClient, socket) {
socket.emit('up_file_slice_fail', error.message)
}
})
// 3. 完成上传
// 3. 合并分片上传到服务器
socket.on('up_file_slice_over', async ({ name, targetFilePath, range, size }) => {
const md5CacheDirPath = rawPath.join(sftpCacheDir, name)
const resultFilePath = rawPath.join(sftpCacheDir, name, name)
Expand Down
29 changes: 16 additions & 13 deletions web/src/views/terminal/components/sftp.vue
Original file line number Diff line number Diff line change
Expand Up @@ -459,15 +459,22 @@ const handleUploadDir = async (event) => {
if (showFileProgress.value) return $message.warning('需等待当前任务完成')
let { files } = event.target
if(files.length === 0) return $message.warning('不允许上传空文件夹')
let folderName = files[0].webkitRelativePath.split('/')[0]
console.log(folderName)
console.log(files)
files = Array.from(files)
// console.log(files)
// 文件夹可能嵌套, 需先创建文件夹
let foldersName = files.map(file => file.webkitRelativePath.split('/').slice(0, -1).join('/'))
if (foldersName.length === 0) return $message.warning('不允许上传空文件夹')
// console.log(foldersName)
let targetDirPath = curPath.value
socket.value.emit('create_remote_dir', { targetDirPath, folderName })
socket.value.once('is_exists_dir', (res) => { $message.error(res) })
socket.value.emit('create_remote_dir', { targetDirPath, foldersName })
socket.value.once('create_remote_dir_exists', (res) => {
$message.error(res)
uploadDirRef.value = null
})
socket.value.once('create_remote_dir_success', async () => {
for (let file of files) {
let fullFilePath = getPath(`${ folderName }/${ file.name }`)
for (let [index, file,] of files.entries()) {
let fullFilePath = getPath(`${ foldersName[index] }/${ file.name }`)
console.log('fullFilePath: ', fullFilePath)
try {
await uploadFile(file, fullFilePath)
} catch (error) {
Expand All @@ -481,16 +488,13 @@ const handleUploadDir = async (event) => {
const uploadFile = (file, targetFilePath) => {
return new Promise((resolve, reject) => {
if (!file) return reject('file is not defined')
// if ((file.size / 1024 / 1024) > 1000) {
// $message.warn('用网页传这么大文件你是认真的吗?')
// }
let reader = new FileReader()
reader.onload = async () => {
const { name } = file
const targetDirPath = curPath.value
curUploadFileName.value = name
const size = file.size
if(size === 0) return reject('文件大小为0KB, 无法上传')
if (size === 0) return reject('文件大小为0KB, 无法上传')
socket.value.emit('create_cache_dir', { targetDirPath, name })
socket.value.once('create_cache_success', async () => {
let start = 0
Expand All @@ -501,7 +505,7 @@ const uploadFile = (file, targetFilePath) => {
try {
upFileProgress.value = 0
showFileProgress.value = true
childDirLoading.value = true
// childDirLoading.value = true
const totalSliceCount = Math.ceil(size / range)
while (end < size) {
fileIndex++
Expand Down Expand Up @@ -563,7 +567,6 @@ const uploadSliceFile = (fileInfo) => {
}
const openDir = (path = '', tips = true) => {
if (showFileProgress.value) return $message.warning('需等待当前任务完成')
childDirLoading.value = true
curTarget.value = null
socket.value.emit('open_dir', path || curPath.value, tips)
Expand Down

0 comments on commit 9889528

Please sign in to comment.