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

news2024/11/18 21:47:53

背景

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

前几天突然想到了一个想法。同学之间平常用网络分享一个文件,大部分都是用的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文档网

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Spark通过三种方式创建DataFrame

通过toDF方法创建DataFrame 通过toDF的方法创建 集合rdd中元素类型是样例类的时候&#xff0c;转成DataFrame之后列名默认是属性名集合rdd中元素类型是元组的时候&#xff0c;转成DataFrame之后列名默认就是_N集合rdd中元素类型是元组/样例类的时候&#xff0c;转成DataFrame…

LLM prompt提示工程调试方法经验技巧汇总

现在接到一个LLM模型任务&#xff0c;第一反应就是能不能通过精调prompt来实现&#xff0c;因为使用prompt不需要训练模型&#xff0c;只需输入指令就可以实现和LLM的交互。按照以往经验&#xff0c;不同的prompt对模型输出影响非常大&#xff0c;如果能构造一个好的prompt&…

工业品电商,新的隐形冠军藏不住了?

【潮汐商业评论/原创】 “时代真的变了。”自打从淘宝买了一批配件后&#xff0c;工厂老板李瓦就经常感慨。 李瓦经营着一家专门生产机器零部件的工厂&#xff0c;日常经常要采购传送带、螺丝、螺母等材料&#xff0c;过去他主要通过线下的方式进货。但最近朋友圈里一段淘宝工…

2023.11.15 hive sql之函数标准,字符串,日期,数学函数

目录 一.函数分类标准 二.查看官方函数,与简单演示 三.3种类型函数演示 四.字符串函数 1.常见字符串函数 2.索引函数 解析函数 五.日期函数 1.获取当前时间 2.获取日期相关 3.周,季度等计算 4.时间戳 六.数学函数 一.函数分类标准 目前hive三大标准 UDF:&#xff08…

社区论坛小程序源码系统,功能齐全,页面简洁,前端+后端+完整部署教程

现如今&#xff0c;社区论坛已经成为人们交流思想&#xff0c;分享经验&#xff0c;获取信息的重要平台。近年来&#xff0c;小程序的出现更是改变了传统的网站建设方式&#xff0c;让用户体验更加便捷&#xff0c;高效。今天源码小编来和大家分享一款社区论坛小程序源码系统&a…

基于SSM的OA办公管理系统的设计与实现

末尾获取源码 开发语言&#xff1a;Java Java开发工具&#xff1a;JDK1.8 后端框架&#xff1a;SSM 前端&#xff1a;Vue 数据库&#xff1a;MySQL5.7和Navicat管理工具结合 服务器&#xff1a;Tomcat8.5 开发软件&#xff1a;IDEA / Eclipse 是否Maven项目&#xff1a;是 目录…

exce常用

一、冻结 同时冻结行和列 打开一个Excel表格&#xff0c;点击选择需要冻结的行和列交接处对应的单元格&#xff08;例如&#xff1a;需要同时冻结1、2行和A、B列&#xff0c;则选中行列交接对应的C3单元格&#xff09;&#xff09;&#xff0c; 即下一行 和下一列的交接点。 …

使用grad-cam对ViT的输出进行可视化

使用grad-cam对ViT的输出进行可视化 文章目录 使用grad-cam对ViT的输出进行可视化前言原理使用代码Pytorch-grad-cam库的更多方法在MMpretrain中使用示例总结 前言 Vision Transformer (ViT) 作为现在CV中的主流backbone&#xff0c;它可以在图像分类任务上达到与卷积神经网络…

mysql数据库超过最大连接数

mysql 超过数据库最大连接数解决办法 1、报错信息 首先无论是navicat 执行sql还是 用idea启动多的服务都会有如下报错信息&#xff1a; 2、解决办法 2.1命令方式修改 这种方法是由其他资料提供的。这种修改方式是临时的&#xff0c;如果mysql服务重启设置就会还原&#xff…

弱类型和强类型自定义UDAF函数

目录 使用自带的avg函数弱类型自定义UDAF函数(AVG)强类型自定义UDAF函数(AVG) 弱类型&#xff1a;3.x过期 2.x有 强类型&#xff1a;3.x 2.x没有 使用自带的avg函数 import org.apache.spark.rdd.RDD import org.apache.spark.sql.{DataFrame, SparkSession}object UserDefine…

双极膜电渗析设备

#双极膜电渗析设备 双极膜&#xff08;bipolar membrance&#xff0c;简称BPM&#xff09;是一种新型的离子交换复合膜&#xff0c;它通常由阳离子交换层&#xff08;N型膜&#xff09;、界面亲水层&#xff08;催化层&#xff09;和阴离子交换膜&#xff08;P型膜&#xff09;…

【计算思维】少儿编程蓝桥杯青少组计算思维题考试真题及解析C

【科技素养】少儿编程蓝桥杯青少组计算思维题考试真题及解析 1.天平的左右两端分别放有一些砝码&#xff0c;如下图所示&#xff0c;右边的砝码不变&#xff0c;从左边最多拿走几个砝码&#xff0c;可以使天平左右两边平衡&#xff1a; A、1 B、2 C、3 D、4 2.把下面的图形…

sqli-labs(Less-3)

1. 通过构造id1’ 和id1’) 和id1’)–确定存在注入 可知原始url为 id(‘1’) 2.使用order by 语句猜字段数 http://127.0.0.1/sqlilabs/Less-3/?id1) order by 4 -- http://127.0.0.1/sqlilabs/Less-3/?id1) order by 3 --3. 使用联合查询union select http://127.0.0.1…

Window MongoDB安装

三种NOSQL的一种,Redis MongoDB ES 应用场景: 1.社交场景:使用Mongodb存储用户信息,以及用户发表的朋友圈信息,通过地理位置索引实现附近的人,地点等功能 2.游戏场景:使用Mongodb存储游戏用户信息,用户的装备,积分等直接以内嵌文档的形式存储,方便查询,高效率存储和访问…

IDEA创建JavaFX项目

1、New -> Project 2、选择JavaFX 配置项目名&#xff0c;包名&#xff0c;lib包管理工具&#xff0c;JDK版本&#xff08;注&#xff0c;JDK版本最低需要11&#xff09; 3、选择lib包 根据自己需求选择 lib包介绍 BootstrapFX&#xff1a;BootstrapFX 是一个为 JavaFX 提…

怎样正确选择等保测评机构开展等保测评工作?

随着大家对网络安全的重视&#xff0c;越来越多的企业需要做等保测评了。很多小伙伴想知道怎样正确选择等保测评机构开展等保测评工作&#xff1f;这里就给大家简单说说。 怎样正确选择等保测评机构开展等保测评工作&#xff1f; 【回答】&#xff1a;正确选择等保测评机构开展…

Java魔法解密:HashMap底层机制大揭秘

文章目录 一、 源码深度解析1.1 窥探Java集合框架中的设计思想1.2 逐行解读HashMap的源代码1.2.1 类信息1.2.2 常量属性1.2.3 变量属性1.2.4 节点信息1.2.5 构造方法1.2.6 put方法1.2.6.1 putVal方法1.2.6.2 putTreeVal方法1.2.6.3 tieBreakOrder方法1.2.6.4 treeifyBin方法1.2…

【联邦学习+区块链】TORR: A Lightweight Blockchain for Decentralized Federated Learning

文章目录 I.CONTRIBUTIONII. ASSUMPTIONS AND THREAT MODELA. AssumptionsB. Threat Model III. SYSTEM DESIGNA. Design OverviewB. Block DesignC. InitializationD. Role SelectionE. Storage ProtocolF. Aggregation ProtocolG. Proof of ReliabilityH. Blockchain Consens…

Hive的安装部署

目录 1.修改hadoop相关参数2.Hive解压安装3.Hive元数据的三种部署方式3.1 元数据库之Derby3.2 元数据库之Mysql3.3 元数据之MetaStore Server 4.hive的两种访问方式4.1 命令行的方式4.2 HiveServer2模式 1.修改hadoop相关参数 1&#xff09;修改core-site.xml [roothadoop102…