django+paramiko结合layui实现webssh,sftp的多文件直传功能

原文地址:django+paramiko结合layui实现webssh,sftp的多文件直传功能

环境准备

python: 3.7.5

django:3.2.15

paramiko:3.1.0

layui:2.8.2

要求django+layui基础环境已经搭建完成。

主方法--views.py

# 上传基于SFTP直传--web终端
@csrf_exempt
@xframe_options_exempt
@k8s.login_auth_required
def webssh_upload_terminal_info(request):
    id = request.GET.get("id")
    remote_path = request.GET.get('selectedFilePath')
    print("文件上传--web终端主机ID:",id)
    print("传递的路径地址:",remote_path)
    return render(request, 'monitor/webssh_upload_terminal.html',{"id":id,"remote_path":remote_path})

@csrf_exempt
@xframe_options_exempt
@k8s.login_auth_required
def webssh_update_file_api(request):
    if request.method == "POST":
        host_ssh_id = request.GET.get('id')
        remote_path = request.POST.get('remote_path')
        file = request.FILES.get('file')
        print("主机ID:",host_ssh_id,"上传路径:",remote_path,"文件:",file)

        # 允许上传的文件格式
        allowed_types = [
            'application/octet-stream',
            'application/zip',
            'application/x-zip-compressed',
            'image/jpeg',
            'image/png',
            'image/gif',
            'image/x-icon',
        ]

        # 如果想不限制文件的上传类型,可以去掉这个判断即可
        if file.content_type in allowed_types:
            # 文件在内存中,将其内容写入临时文件
            with tempfile.NamedTemporaryFile(delete=False) as temp_file:
                temp_file.write(file.read())
                file_path = temp_file.name
            
            print("文件临时路径:",file_path)
            try:
                # 通过ID在数据库中查出用于认证的信息并建立连接
                host_ssh = HostMonitoring.objects.get(id=host_ssh_id)
                host_ip = host_ssh.ipv4_address
                host_port = int(host_ssh.port)
                sys_user_name = host_ssh.username
                sys_user_passwd = host_ssh.password
                try:
                    # 建立SSH连接
                    with paramiko.Transport((host_ip, host_port)) as sftp_client:
                        sftp_client.connect(username=sys_user_name, password=sys_user_passwd)
                        sftp = paramiko.SFTPClient.from_transport(sftp_client)
                        sftp.put(file_path, remote_path + '/' + file.name)
                        sftp_client.close()
                    return JsonResponse({'success': True, 'message': '文件上传成功'})
                except HostMonitoring.DoesNotExist:
                    return JsonResponse({'success': False, 'message': '无效的主机ID'})
                except Exception as e:
                    return JsonResponse({'success': False, 'message': str(e)})
            except Exception as e:
                return JsonResponse({'success': False, 'message': '数据库连接异常'})
        else:
            print("上传失败",file.content_type)
            return JsonResponse({'success': False, 'message': '无效的文件类型'})
    else:
        return JsonResponse({'success': False, 'message': '请求方法错误'})

前端文件--webssh_upload_terminal.html

<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>文件上传</title>
  <link href="/static/layui/css/layui.css" rel="stylesheet" type="text/css"/>
  <style>
    .upload-status {
      font-weight: bold;
    }
    .upload-success {
      color: green;
    }
    .upload-failed {
      color: red;
    }
  </style>
</head>
<body>
    <div class="layui-upload">
      <div class="layui-inline">
        <button type="button" class="layui-btn layui-btn-normal" id="ID-upload-demo-files">选择多文件</button>
      </div>
      <!-- <div class="layui-inline">
        <label class="layui-form-label">远程路径:</label>
        <div class="layui-input-inline">
            <input type="text" id="remote-path" placeholder="请输入远程存储路径" autocomplete="off" class="layui-input">
        </div>
      </div> -->
      <div class="layui-inline">
        <button type="button" class="layui-btn layui-btn-warm" id="ID-upload-demo-files-action">开始上传</button> 
    </div>
        <div class="layui-upload-list">
          <table class="layui-table">
            <colgroup>
              <col style="min-width: 100px;">
              <col width="150">
              <col width="260">
              <col width="150">
            </colgroup>
            <thead>
              <th>文件名</th>
              <th>大小</th>
              <th>上传进度</th>
              <th>操作</th>
            </thead>
            <tbody id="ID-upload-demo-files-list"></tbody>
          </table>
        </div>
      </div>

<script src="/static/layui/layui.js"></script>
<script>
  layui.use(['jquery','upload','element'],function(upload){
    var upload = layui.upload;
    var element = layui.element;
    var $ = layui.$;
    var hostId = "{{ id }}";
    var remote_path = "{{ remote_path }}";
    console.log("第二层弹出上传栏:" + remote_path)
    var uploadListIns = upload.render({
      elem: '#ID-upload-demo-files',
      elemList: $('#ID-upload-demo-files-list'),
      url: '{% url "webssh_update_file_api" %}?id=' + hostId,
      accept: 'file',
      multiple: true,
      number: 10,
      auto: false,
      data:{remote_path: ''},
      bindAction: '#ID-upload-demo-files-action',
      before: function(obj){
        this.data.remote_path = remote_path
      },
      choose: function(obj){  
        var that = this;
        var files = this.files = obj.pushFile();
        
        obj.preview(function(index, file, result){
          var tr = $(['<tr id="upload-'+ index +'">',
            '<td>'+ file.name +'</td>',
            '<td>'+ (file.size/1024/1024).toFixed(1) +'Mb</td>',
            '<td><div class="layui-progress" lay-filter="progress-demo-'+ index +'"><div class="layui-progress-bar" lay-percent=""></div></div></td>',
            '<td><button class="layui-btn layui-btn-xs demo-delete">删除</button></td>',
            '<td id="status-'+ index +'" class="upload-status">等待上传</td>',
          '</tr>'].join(''));
          
          tr.find('.demo-delete').on('click', function(){
            delete files[index];
            tr.remove();
            uploadListIns.config.elem.next()[0].value = ''; 
          });
          
          that.elemList.append(tr);
          element.render('progress');
        });
      },
      done: function(res, index, upload){
        var statusElem = $('#status-' + index);
        if (res.success) {
          statusElem.html('<span class="upload-success">上传成功</span>');
        } else {
          statusElem.html('<button class="layui-btn layui-btn-xs demo-reload">重传</button>' +
                          '<button class="layui-btn layui-btn-xs layui-btn-danger demo-delete">删除</button>');
        }
      },
      error: function(index, upload){
        var statusElem = $('#status-' + index);
        statusElem.html('<button class="layui-btn layui-btn-xs demo-reload">重传</button>' +
                        '<button class="layui-btn layui-btn-xs layui-btn-danger demo-delete">删除</button>');
      },
      progress: function(n, elem, e, index){
        var statusElem = $('#status-' + index);
        statusElem.text('上传中 ' + n + '%');
        element.progress('progress-demo-'+ index, n + '%');
      }
    });
    
    $('#ID-upload-demo-files-action').on('click', function(){
      // Change the status to "上传中" for all selected files
      $('.upload-status').text('上传中 0%').addClass('upload-failed').removeClass('upload-success');
      $('.layui-progress-bar').css('width', '0%');
    });
  });
</script>
</body>
</html>

前端文件--webssh_file.html

<!--文件sftp直传代码-->
  <script>
    layui.use('layer', function () {
      var layer = layui.layer;
      var hostId = "{{ id }}";

      $('#upload').on('click', function () {
        var selectedFilePath = $("#current-path").val();
        console.log("获取到的路径" + selectedFilePath)
        layer.open({
          type: 2,
          offset: 'r',
          anim: 'slideLeft', // 从右往左
          area: ['70%', '100%'],
          closeBtn: true, // 1或者2表示开启关闭按钮,0表示不开启
          title: "文件管理器",
          shade: 0.1,
          shift: 2,
          shadeClose: false,
          id: 'ID-demo-layer-direction-r', //2.8.0新特性,抽屉效果
          content: '{% url "webssh_upload_terminal_info" %}?id=' + hostId + '&selectedFilePath=' + selectedFilePath,
          move: false, // 禁止拖动
          resize: false, // 禁止调整大小
          skin: 'white-background' // 应用自定义的背景颜色类 
        });
      });
    });
  </script>
  <!--上传进度条弹窗-->
  <div id="file-upload-progress" style="margin:50px 0 0 50px;display: none;">
    <div id="picker" style="float:left;">请选择</div>
    <div id="progress" class="progress" style="width:500px;float:left;margin:10px 0 0 20px;">
      <div class="progress-bar progress-bar-striped active" role="progressbar" style="width:0%;"></div>
    </div>
    <div style="clear:both;"></div>
  </div>

  <!--头部选项栏-->
  <div class="layui-container">
    <div class="layui-row layui-col-space15">
      <div class="layui-col-md12">
        <fieldset class="layui-elem-field layui-field-title">
          <legend>Linux 文件管理器</legend>
          <div class="layui-field-box">
            <div class="layui-form-item">
              <button id="go-back" class="layui-btn return-btn control-btn">返回</button>
              <label class="layui-form-label" style="margin-left: 20px;">当前路径:</label>
              <div class="layui-input-inline">
                <input type="text" id="current-path" value="/" readonly class="layui-input">
              </div>
              <button class="layui-btn control-btn action-btn" data-action="createDir">新建目录</button>
              <!-- 设置一个隐藏的file input接收用户上传的文件-->
              <input type="file" id="file-upload" style="display: none;">
              <!--将上传文件按钮设为触发file input的点击事件-->
              <button class="layui-btn layui-btn-normal control-btn upload-file" id="upload" data-action="upload">上传文件</button>  <!--文件sftp直传方式入口-->
              <!-- 实现弹出层 -->
              <button id="test1">查看上传进度</button> <!-- 触发按钮 -->
              <button id="refresh" class="layui-btn layui-btn-normal control-btn">刷新</button>
            </div>
            <table id="file-table" lay-filter="demo"></table>
            <script type="text/html" id="operations">
              <button class="layui-btn layui-btn-xs layui-btn-normal download" data-action="download">下载</button>
              <button class="layui-btn layui-btn-xs layui-btn-danger delete" data-action="delete">删除</button>
          </script>
          </div>
        </fieldset>
      </div>
    </div>
  </div>

效果图如下

sftp_upload.gif

这段代码的流程如下:linux 文件管理器选择要上传的文件目录》选择上传》选择文件》开始上传 如果上传失败,会显示重传按钮,功能还没实现,上传文件会先保存到/tmp临时目录下,上传浏览器端上传主机完成,会写入到用户选择的上传目录下。

这个版本体验要好一点了,且支持多文件同时上传,但仍需要打磨。

 

### 回答1: 要实现婚庆系统源码,可以使用PythonDjango框架和Layui前端框架进行开发。 首先,使用Django框架进行后端开发。可以创建一个Django项目,并建立婚庆系统所需的数据库模型。可以创建Wedding模型来存储婚庆相关的信息,例如婚礼日期、地点、主持人、新郎新娘姓名等。同时,可以建立Guest模型来存储婚宴中的宾客信息,例如姓名、座位号、是否到场等。还可以创建其他需要的模型,如宴会厅、菜单、花艺等。 然后,使用Django的视图函数和URL配置来处理前端请求。可以创建婚庆系统的各个页面,例如首页、婚礼详情页、宾客管理页等,并编写相应的视图函数来处理前端请求,如获取婚礼列表、添加宾客、修改宾客信息等。 接下来,使用Layui前端框架来美化页面和实现交互效果。可以利用Layui的模块化和响应式特性,使用其提供的组件和样式来构建婚庆系统的前端界面。可以使用Layui的表格组件来展示宾客列表,并加入搜索、排序等功能。还可以使用Layui的表单组件来实现添加宾客、修改宾客信息等功能。此外,还可以利用Layui的弹层组件来实现弹出式的提示框、确认框等。 最后,将后端和前端进行整合,完成婚庆系统的开发。可以使用Django的模板引擎来渲染页面,并将前端的静态资源(如CSS、JavaScript等)与Django项目的静态文件进行整合。 通过以上步骤,就可以使用PythonDjango框架和Layui前端框架来实现婚庆系统的源码。 ### 回答2: 实现婚庆系统源码可以使用PythonDjangoLayui这三个技术来完成。 第一步是使用PythonDjango搭建婚庆系统的后台,包括用户管理、订单管理、商家管理和产品管理等功能。通过Django框架可以快速搭建起数据库模型和后台逻辑,并使用Python编写相应的业务逻辑代码。例如,通过Django提供的User模型可以实现用户登录注册功能,通过自定义模型可以实现订单和商家的管理功能。 第二步是使用Layui搭建婚庆系统的前端页面,包括用户登录注册界面、订单提交界面、商家信息展示界面等。Layui是一款非常方便易用的前端UI框架,可以大大简化前端开发的工作。通过Layui提供的各种组件和样式,可以完成婚庆系统的页面设计和交互效果的实现。 最后,将Django后台和Layui前端进行整合,实现婚庆系统的完整功能。通过Django提供的视图函数和URL路由功能,将前端页面和后台代码连接在一起。例如,用户在Layui前端页面上提交订单后,通过Django后台的视图函数进行订单数据的处理和保存。 总结起来,使用PythonDjango框架搭建婚庆系统的后台,使用Layui搭建婚庆系统的前端页面,然后将两者进行整合,就可以实现婚庆系统的源码编写。这样的婚庆系统可以提供用户注册和登录、订单提交和管理、商家信息展示和管理等功能。 ### 回答3: Python是一种高级编程语言,它非常适合用来开发Web应用程序。Django是一个流行的Python Web框架,它提供了许多用于开发高质量Web应用程序的工具和功能。而Layui则是一个轻量级的前端框架,它基于HTML和CSS,提供了丰富的界面组件和易用的样式。 要实现一个婚庆系统的源码,我们可以使用PythonDjango框架和Layui前端框架。 首先,我们可以使用Django创建一个新的Web应用程序。在Django中,我们可以定义模型来建立数据库结构,例如婚礼、预订、客户等。我们可以使用Django的自带命令行工具生成数据库迁移文件,并将其应用到数据库中。 接下来,我们可以使用Django的视图来处理用户的请求并渲染相应的模板。通过使用Django的模板语言,我们可以根据数据动态地生成HTML页面。在模板中,我们可以使用Layui的UI组件来构建用户界面,例如表格、表单、日期选择器等。 在后端逻辑方面,我们可以编写Django的视图函数来处理用户的请求,例如创建新的婚礼预订、展示所有的预订信息等。我们可以使用Django的表单功能来验证和处理用户提交的数据,并将数据保存到数据库中。 在前端方面,我们可以使用LayuiJavaScript库来增强用户交互体验。例如,我们可以使用Layui的表单验证功能来确保用户输入的数据的合法性。我们还可以使用Layui的弹窗组件来显示提示信息或确认对话框。 同时,为了增加用户的安全性,我们可以使用Django提供的用户认证系统来管理用户的登录和权限。 总结起来,使用PythonDjango框架和Layui前端框架,我们可以轻松实现一个婚庆系统的源码。通过使用Django的模型、视图和模板,以及Layui的界面组件和样式,我们可以构建一个功能完善且美观的婚庆系统。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

llody_55

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值