U 文件管理器链接文件可点击

pull/410/head
vapao 2021-11-05 18:43:18 +08:00
parent 02828e6c6c
commit 0395eb5ab5
3 changed files with 46 additions and 34 deletions

View File

@ -4,6 +4,7 @@
from django.http import FileResponse from django.http import FileResponse
import stat import stat
import time import time
import os
KB = 1024 KB = 1024
MB = 1024 * 1024 MB = 1024 * 1024
@ -25,21 +26,21 @@ def parse_mode(obj):
if obj.st_mode: if obj.st_mode:
mt = stat.S_IFMT(obj.st_mode) mt = stat.S_IFMT(obj.st_mode)
if mt == stat.S_IFIFO: if mt == stat.S_IFIFO:
kind = "p" kind = 'p'
elif mt == stat.S_IFCHR: elif mt == stat.S_IFCHR:
kind = "c" kind = 'c'
elif mt == stat.S_IFDIR: elif mt == stat.S_IFDIR:
kind = "d" kind = 'd'
elif mt == stat.S_IFBLK: elif mt == stat.S_IFBLK:
kind = "b" kind = 'b'
elif mt == stat.S_IFREG: elif mt == stat.S_IFREG:
kind = "-" kind = '-'
elif mt == stat.S_IFLNK: elif mt == stat.S_IFLNK:
kind = "l" kind = 'l'
elif mt == stat.S_IFSOCK: elif mt == stat.S_IFSOCK:
kind = "s" kind = 's'
else: else:
kind = "?" kind = '?'
code = obj._rwx( code = obj._rwx(
(obj.st_mode & 448) >> 6, obj.st_mode & stat.S_ISUID (obj.st_mode & 448) >> 6, obj.st_mode & stat.S_ISUID
) )
@ -49,10 +50,9 @@ def parse_mode(obj):
code += obj._rwx( code += obj._rwx(
obj.st_mode & 7, obj.st_mode & stat.S_ISVTX, True obj.st_mode & 7, obj.st_mode & stat.S_ISVTX, True
) )
return kind + code
else: else:
kind = "?" return '?---------'
code = '---------'
return kind, code
def format_size(size): def format_size(size):
@ -70,18 +70,32 @@ def format_size(size):
return '' return ''
def parse_sftp_attr(obj): def fetch_dir_list(host, path):
if (obj.st_mtime is None) or (obj.st_mtime == int(0xffffffff)): with host.get_ssh() as ssh:
date = "(unknown date)" objects = []
for item in ssh.list_dir_attr(path):
code = parse_mode(item)
kind, is_link, name = '?', False, getattr(item, 'filename', '?')
if stat.S_ISLNK(item.st_mode):
is_link = True
try:
item = ssh.sftp_stat(os.path.join(path, name))
except FileNotFoundError:
pass
if stat.S_ISREG(item.st_mode):
kind = '-'
elif stat.S_ISDIR(item.st_mode):
kind = 'd'
if (item.st_mtime is None) or (item.st_mtime == int(0xffffffff)):
date = '(unknown date)'
else: else:
date = time.strftime('%Y/%m/%d %H:%M:%S', time.localtime(obj.st_mtime)) date = time.strftime('%Y/%m/%d %H:%M:%S', time.localtime(item.st_mtime))
kind, code = parse_mode(obj) objects.append({
is_dir = stat.S_ISDIR(obj.st_mode) if obj.st_mode else False 'name': name,
size = obj.st_size or '' 'size': '' if kind == 'd' else format_size(item.st_size or ''),
return {
'name': getattr(obj, 'filename', '?'),
'size': '' if is_dir else format_size(size),
'date': date, 'date': date,
'kind': kind, 'kind': kind,
'code': code 'code': code,
} 'is_link': is_link
})
return objects

View File

@ -5,7 +5,7 @@ from django.views.generic import View
from django_redis import get_redis_connection from django_redis import get_redis_connection
from apps.host.models import Host from apps.host.models import Host
from apps.account.utils import has_host_perm from apps.account.utils import has_host_perm
from apps.file.utils import FileResponseAfter, FileResponse, parse_sftp_attr from apps.file.utils import FileResponseAfter, fetch_dir_list
from libs import json_response, JsonParser, Argument from libs import json_response, JsonParser, Argument
from functools import partial from functools import partial
import os import os
@ -23,9 +23,8 @@ class FileView(View):
host = Host.objects.get(pk=form.id) host = Host.objects.get(pk=form.id)
if not host: if not host:
return json_response(error='未找到指定主机') return json_response(error='未找到指定主机')
with host.get_ssh() as ssh: objects = fetch_dir_list(host, form.path)
objects = ssh.list_dir_attr(form.path) return json_response(objects)
return json_response([parse_sftp_attr(x) for x in objects])
return json_response(error=error) return json_response(error=error)

View File

@ -39,8 +39,8 @@ class FileManager extends React.Component {
key: 'name', key: 'name',
render: info => info.kind === 'd' ? ( render: info => info.kind === 'd' ? (
<div onClick={() => this.handleChdir(info.name, '1')} style={{cursor: 'pointer'}}> <div onClick={() => this.handleChdir(info.name, '1')} style={{cursor: 'pointer'}}>
<FolderOutlined style={{color: '#1890ff'}}/> <FolderOutlined style={{color: info.is_link ? '#008b8b' : '#1890ff'}}/>
<span style={{color: '#1890ff', paddingLeft: 5}}>{info.name}</span> <span style={{color: info.is_link ? '#008b8b' : '#1890ff', paddingLeft: 5}}>{info.name}</span>
</div> </div>
) : ( ) : (
<React.Fragment> <React.Fragment>
@ -61,8 +61,7 @@ class FileManager extends React.Component {
width: 190 width: 190
}, { }, {
title: '属性', title: '属性',
key: 'attr', dataIndex: 'code',
render: info => `${info.kind}${info.code}`,
width: 110 width: 110
}, { }, {
title: '操作', title: '操作',