基于flask和fomantic-ui的简易p2p文件分享平台的手动实现

背景

开学一个多月了,由于繁重的学业和懒惰,都没怎么更新有意思的博客。

前几天突然想到了一个想法。同学之间平常用网络分享一个文件,大部分都是用的qq。但是qq看起来把文件拖到聊天框点击发送就发给对面同学了。但是实际上是先上传到了腾讯的服务器,然后对面的同学再从服务器上下载。

这一上传一下载就很耽误时间。我就想在我的电脑上开一个文件上传服务,别的同学直接上传到我的机械革命上,上传完毕,我就得到了这个文件,不用再下载一遍。而且由于是校园网内的服务,速度也有保障。

语言选择

由于前几天做了几道python flask模板注入的题目,便打算拿flask来当后端练练手,提供http服务。

前端的话还是利用漂亮且方便易用的fomantic-ui解决html和css样式问题,再配合上大大简化js编程的Jquery来写效果和功能。

遇到的困难

单纯的文件上传十分简单。对付小文件还好,但是大文件就会出现页面停滞的情况,而用户收不到任何反馈,不知道到底是在上传还是崩溃了。我们需要设置一个上传进度条来给以用户友善的提示。所以这里就有一个问题,如何获得上传的进度?

查询资料过后,我发现XMLHttpRequest能够获取进度。然后我又发现Jquery中封装的$.ajax能够更加简单的实现。参考链接 https://stackoverflow.com/questions/13203231/is-there-any-way-to-get-jquery-ajax-upload-progress

代码

文件目录

文件目录

文件目录

<!DOCTYPE html>
<html>
<head>
  <meta charset="utf8" />
  <script src="https://cdn.jsdelivr.net/npm/jquery@3.3.1/dist/jquery.min.js"></script>
  <link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/npm/fomantic-ui@2.8.8/dist/semantic.min.css" />
  <script src="https://cdn.jsdelivr.net/npm/fomantic-ui@2.8.8/dist/semantic.min.js"></script>
  <title>wuuconix's page</title>
</head>
<body>
    <div style="padding-top: 5em;"></div>
    <div class="ui text container">
        <div class="ui placeholder segment">
            {% if filelist == [] %}
                <div class="ui icon header">
                    <i class="pdf file outline icon"></i>
                    目前文件夹里空空如也
                </div>
            {% else %}
                <div class="ui list">
                {% for file in filelist%}
                    <div class="item">
                        <i class="file icon"></i>
                        <div class="content">
                            <a class="header" href="download/{{file}}" data-content="点击下载{{file}}" id="files">{{file}}</a>
                        </div>
                    </div>
                {% endfor %}
                </div>
            {% endif %}
            <div class="ui buttons">
                <button class="ui primary button" id="button_choose">选择文件</button>
                <button class="ui positive button" id="button_submit">上传</button>
            </div>
            <form action="/upload" method="post" enctype="multipart/form-data" id="form">
                <input type="file" id="input_file" style="display: none;" name="file">
            </form>
            <div class="ui divider"></div>
            <div class="ui indicating progress" id="progress" data-value="0" data-total="100"> 
                <div class="bar">
                    <div class="progress"></div>
                </div>
                <div class="label"></div>
            </div>
        </div>
    </div>
</body>

<script>
    $(document).ready(function(){
        $("#progress").hide();
        $("#button_submit").attr("disabled", true);
    });
    $("#button_choose").click(function()
    {
        $("#input_file").click();
    });
    $("#input_file").bind("input propertychange",function(){
        var name = ($(this).prop('files')[0]['name']);
        $("#button_submit").attr("disabled", false);
        $('#button_choose')[0].innerHTML=name;
    });
    $("#button_submit").click(function()
    {
        $("#progress").show();
        var formdata = new FormData($("#form")[0]); 
        $.ajax({
            url:'/upload', 
            type:'post', 
            xhr: function () {
                var xhr = $.ajaxSettings.xhr();
                var starttime = Math.ceil(new Date().getTime() / 1000);
                xhr.upload.onprogress = function (e) {
                    if (e.lengthComputable) {
                        var uploaded = Math.ceil(e.loaded / Math.pow(1024,2));
                        var spenttime = Math.ceil(new Date().getTime() / 1000) - starttime;
                        var speed = (uploaded / spenttime).toFixed(2);
                        var progress = Math.ceil(e.loaded / e.total * 100);
                        $("#progress").attr('data-value', progress);
                        $("#progress").progress('update progress', progress);
                        $("#progress").progress('set label', speed + "MB/s");
                    }
                };
                return xhr;
            },
            processData:false, 
            contentType:false, 
            data:formdata,
            success:function (data) {
                $('body').toast({
                    title: '恭喜你',
                    message: "你已经成功将 《" + $('#button_choose')[0].innerHTML + "》 上传至了武丑兄的机械革命。页面即将自动刷新",
                    showProgress: 'bottom',
                    classProgress: 'red'
                });
                setTimeout("location.reload();", 3000)  
            }
        })
    });
    $('#progress').progress({
        label: 'percent',
    });
    $('a').popup({
        on: 'hover'
    });
    $("#button_submit").popup({
        on: 'hover'
    });
</script>
from flask import render_template, Flask, request, make_response, send_from_directory
import os

def get_filelist():
    filelist = os.listdir("upload/")
    return filelist

app = Flask(__name__)

@app.route('/')
def hello(filelist=[]):
    return render_template("index.html", filelist=get_filelist())

@app.route('/upload',methods=['GET','POST'])
def upload():
    if request.method == 'POST':
        f = request.files['file']
        print(request.files)
        f.save(f"upload/{f.filename}")
        filelist = get_filelist()
        return render_template("index.html", filelist=filelist)
    else:
        return render_template("index.html", filelist=get_filelist())

@app.route('/download/<filename>',methods=['GET'])
def download(filename):
    response = make_response(send_from_directory("upload", filename, as_attachment=True))
    response.headers["Content-Disposition"] = "attachment; filename={}".format(filename.encode().decode('latin-1'))
    return response
  
if __name__ == '__main__':
    app.run(host='0.0.0.0', port=80)

效果

界面

界面

界面

上传1

上传1

上传2

上传2

上传3

上传3

转载申明

本文转载自腾讯博客,转载请注明出处:365文档网

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/159759.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【C语言期末不挂科——指针篇1】

C语言指针初阶 文章目录 C语言指针初阶**什么是指针&#xff1f;**   **1&#xff09;初识指针**  **2&#xff09;地址的大小**  **3&#xff09;指针变量** **指针的类型**   **1)指针对整数加减运算**  **2&#xff09;指针的解引用** **野指针**  **1&#xff…

河北大学选择ZStack Cube超融合一体机打造实训云平台

河北大学通过云轴科技ZStack Cube超融合一体机构建校园实训云平台&#xff0c;部署测试仅耗时1天&#xff0c;该平台能够更快地为学生提供高性能、高可用的云主机、云存储和云网络服务&#xff1b;同时也能满足日常运维管理要求&#xff0c;为学生提供更好的实训环境。 河北省…

什么是NoSQL?什么是redis?redis是做什么的?

redis官网 NoSQL泛指非关系型数据库&#xff0c;redis是其中的一种&#xff0c;Redis是发展最快的。 什么是NoSQL&#xff1f; NoSQL是一个广义的术语&#xff0c;指的是非关系型数据库&#xff0c;不同于传统的关系型数据库&#xff08;如MySQL、Oracle等&#xff09;。它没有…

(二)Pytorch快速搭建神经网络模型实现气温预测回归(代码+详细注解)

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言一、数据集二、导入数据以及展示部分1.导入数据集以及对数据集进行处理2.展示数据&#xff08;看看就好&#xff09; 三&#xff08;1&#xff09;、搭建网络进…

Diagrams——制作短小精悍的流程图

今天为大家分享的是一款轻量级的流程图绘制软件——Diagrams。 以特定的图形符号加上说明&#xff0c;表示算法的图&#xff0c;称为流程图或框图。流程图是流经一个系统的信息流、观点流或部件流的图形代表。我们常用流程图来说明某一过程。 流程图使用一些标准符号代表某些类…

计算数组中每个元素的立方根numpy.cbrt()

【小白从小学Python、C、Java】 【计算机等级考试500强双证书】 【Python-数据分析】 计算数组中每个元素的立方根 numpy.cbrt() [太阳]选择题 请问以下代码中执行语句输出结果是&#xff1f; import numpy as np a np.array([1, 8, 27]) print("【显示】a ",a) pr…

二维码智慧门牌管理系统升级,异常门牌聚合解决方案助力高效管理

文章目录 前言一、异常门牌聚合解决方案 前言 在今天的数字化时代&#xff0c;智慧城市已成为发展趋势&#xff0c;其中二维码智慧门牌管理系统扮演着至关重要的角色。通过对门牌信息进行数字化管理&#xff0c;该系统极大提升了城市管理的效率和便捷性。然而&#xff0c;随着…

QMenuBar和QToolBar使用同一个QAction

文章目录 前言一、编辑QMenuBar二、将QMenuBar中的Action添加到toolbar总结 前言 qmenubar中的action添加到toolbar&#xff0c;不是在toolbar中再添加action&#xff0c;效果图如下 一、编辑QMenuBar 正常编辑QMenuBar&#xff0c;以下图为例 二、将QMenuBar中的Action添…

logistic回归后快速绘制亚组森林图!SCI发表级高清图片分分钟生成!

本周为大家重点介绍一下风暴统计平台的最新板块——亚组森林图&#xff01; 现在亚组分析好像越来越流行&#xff0c;无论是观察性研究还是RCT研究&#xff0c;亚组分析一般配备森林图。 比如这张图&#xff1a; 还有这个&#xff1a; 森林图不仅是画图的画法&#xff0c;背后还…

算法 LeetCode 题解 | 有效的括号

大家好&#xff0c;我是木川 一、题目描述 给定一个只包括 (&#xff0c;)&#xff0c;{&#xff0c;}&#xff0c;[&#xff0c;] 的字符串 s &#xff0c;判断字符串是否有效。 有效字符串需满足&#xff1a; 左括号必须用相同类型的右括号闭合。左括号必须以正确的顺序闭合。…

Java源码分析:Guava之不可变集合ImmutableMap的源码分析

原创/朱季谦 一、案例场景 遇到过这样的场景&#xff0c;在定义一个static修饰的Map时&#xff0c;使用了大量的put()方法赋值&#xff0c;就类似这样—— public static final Map<String,String> dayMap new HashMap<>(); static {dayMap.put("Monday&q…

Apache Airflow (十) :SSHOperator及调度远程Shell脚本

&#x1f3e1; 个人主页&#xff1a;IT贫道_大数据OLAP体系技术栈,Apache Doris,Clickhouse 技术-CSDN博客 &#x1f6a9; 私聊博主&#xff1a;加入大数据技术讨论群聊&#xff0c;获取更多大数据资料。 &#x1f514; 博主个人B栈地址&#xff1a;豹哥教你大数据的个人空间-豹…

【计算机网络笔记】ICMP(互联网控制报文协议)

系列文章目录 什么是计算机网络&#xff1f; 什么是网络协议&#xff1f; 计算机网络的结构 数据交换之电路交换 数据交换之报文交换和分组交换 分组交换 vs 电路交换 计算机网络性能&#xff08;1&#xff09;——速率、带宽、延迟 计算机网络性能&#xff08;2&#xff09;…

农户建档管理系统的设计与实现-计算机毕业设计源码20835

摘 要 随着互联网趋势的到来&#xff0c;各行各业都在考虑利用互联网将自己推广出去&#xff0c;最好方式就是建立自己的互联网系统&#xff0c;并对其进行维护和管理。在现实运用中&#xff0c;应用软件的工作规则和开发步骤&#xff0c;采用Java技术建设农户建档管理系统。 本…

项目技术复盘

背景 该项目接手时已是8月中下旬&#xff0c;并且客户要求九月中旬输出第一版本。这么紧急的节奏&#xff0c;不知道商务是如何答应的。临危受命&#xff0c;让我承担开发经理岗位&#xff0c;主导该项目。 开发团队 岗位 人员 base 架构师兼高级软件工程师 季工 上海 高…

Java中利用OpenCV进行人脸识别

OpenCV 概述 ​ OpenCV&#xff08;Open Source Computer Vision Library&#xff09;是一个开源计算机视觉库&#xff0c;它提供了丰富的工具和算法&#xff0c;用于处理图像和视频数据。该库由一系列高效的计算机视觉算法组成&#xff0c;涵盖了许多领域&#xff0c;包括目…

C++单调向量算法:132 模式解法三枚举1

本题不同解法 包括题目及代码C二分查找算法&#xff1a;132 模式解法一枚举3C二分查找算法&#xff1a;132 模式解法二枚举2代码最简洁C二分查找算法&#xff1a;132 模式解法三枚举1性能最佳C单调向量算法&#xff1a;132 模式解法三枚举1 分析 时间复杂度 2轮循环时间复杂…

「引流工具」火炬多平台多功能引流高效推广脚本,抖音+快手+小红书多平台自动引流软件

全自动多平台多功能引流脚本&#xff1a; 脚本支持斗音&#xff0c;快手&#xff0c;小红薯&#xff0c;扣扣。默默&#xff0c;弹弹&#xff0c;金日头条&#xff0c;微博&#xff0c;知乎&#xff0c;bibi&#xff0c;易车&#xff0c;最右&#xff0c;美团&#xff0c;汽车…

微软正式宣布其首款人工智能芯片 Maia 100 及基于 Arm 的通用计算芯片 Cobalt 100

微软确认了此前的传闻&#xff1a;该公司已自主开发了 AI 芯片&#xff0c;旨在训练大型语言模型&#xff0c;减少对 Nvidia 的依赖。此外&#xff0c;微软还研制了自家的基于 Arm 架构的 CPU&#xff0c;专为云计算工作负载设计。这两款定制硅芯片旨在为其 Azure 数据中心提供…

Axure基础详解二十:中继器随机抽奖效果

效果演示 组件 一、中继器 建立一个“中继器”内部插入一个“正方形”&#xff0c;给“正方形”添加一个【样式效果】>>【选中状态】填充背景为红色&#xff0c;字体白色。在中继器表格中插入两列数据函数&#xff1a;【xuhao】(序号列&#xff0c;按12345……填写&…