• 企业400电话
  • 微网小程序
  • AI电话机器人
  • 电商代运营
  • 全 部 栏 目

    企业400电话 网络优化推广 AI电话机器人 呼叫中心 网站建设 商标✡知产 微网小程序 电商运营 彩铃•短信 增值拓展业务
    90行Python代码开发个人云盘应用

    本文示例代码已上传至我的Github仓库https://github.com/CNFeffery/DataScienceStudyNotes

    1 简介

    在今天的教程中,我们将介绍如何在Dash中高效地开发web应用中非常重要的「文件上传」及「下载」功能。

    2 在Dash中实现文件上传与下载

    2.1 在Dash中配合dash-uploader实现文件上传

    其实在自带的dash_core_components中就封装了基于html5原生API的dcc.Upload()组件,可以实现简单的文件上传功能,但说实话,非常的「不好用」,其主要缺点有:

    正是因为Dash自带的上传部件如此不堪,所以一些优秀的第三方拓展涌现出来,其中最好用的要数dash-uploader,它解决了上面提到的dcc.Upload()的所有短板。通过pip install dash-uploader进行安装之后,就可以直接在Dash应用中使用了。

    我们先从极简的一个例子出发,看一看在Dash中使用dash-uploader的正确姿势:

    app1.py

    import dash
    import dash_uploader as du
    import dash_bootstrap_components as dbc
    import dash_html_components as html
    
    app = dash.Dash(__name__)
    
    # 配置上传文件夹
    du.configure_upload(app, folder='temp')
    
    app.layout = html.Div(
        dbc.Container(
            du.Upload()
        )
    )
    
    if __name__ == '__main__':
        app.run_server(debug=True)

    可以看到,仅仅十几行代码,我们就配合dash-uploader实现了简单的文件上传功能,其中涉及到dash-uploader两个必不可少的部分:

    2.1.1 利用du.configure_upload()进行配置

    要在Dash中正常使用dash-uploader,我们首先需要利用du.configure_upload()进行相关配置,其主要参数有:

    「app」,即对应已经实例化的Dash对象;

    「folder」,用于设置上传的文件所保存的根目录,可以是相对路径,也可以是绝对路径;

    「use_upload_id」,bool型,默认为True,这时被用户上传的文件不会直接置于「folder」参数指定目录,而是会存放于du.Upload()部件的upload_id对应的子文件夹之下;设置为False时则会直接存放在根目录,当然没有特殊需求还是不要设置为False。

    通过du.configure_upload()我们就完成了基本的配置。

    2.1.2 利用du.Upload()创建上传部件

    接下来我们就可以使用到du.Upload()来创建在浏览器中渲染供用户使用的上传部件了,它跟常规的Dash部件一样具有「id」参数,也有一些其他的丰富的参数供开发者充分自由地自定义功能和样式:

    「text」,字符型,用于设置上传部件内显示的文字;

    「text_completed」,字符型,用于设置上传完成后显示的文字内容前缀;

    「cancel_button」,bool型,用于设置是否在上传过程中显示“取消”按钮;

    「pause_button」,bool型,用于设置是否在上传过程中显示“暂停”按钮;

    「filetypes」,用于限制用户上传文件的格式范围,譬如['zip', 'rar', '7zp']就限制用户只能上传这三种格式的文件。默认为None即无限制;

    「max_file_size」,int型,单位MB,用于限制单次上传的大小上限,默认为1024即1GB;

    「default_style」,类似常规Dash部件的style参数,用于传入css键值对,对部件的样式进行自定义;

    「upload_id」,用于设置部件的唯一id信息作为du.configure_upload()中所设置的缓存根目录的下级子目录,用于存放上传的文件,默认为None,会在Dash应用启动时自动生成一个随机值;

    「max_files」,int型,用于设置一次上传最多可包含的文件数量,默认为1,也推荐设置为1,因为目前对于多文件上传仍有「进度条异常」、「上传结束显示异常」等bug,所以不推荐设置大于1。

    知晓了这些参数的作用之后,我们就可以创建出更符合自己需求的上传部件:

    app2.py

    import dash
    import dash_uploader as du
    import dash_bootstrap_components as dbc
    import dash_html_components as html
    
    app = dash.Dash(__name__)
    
    # 配置上传文件夹
    du.configure_upload(app, folder='temp')
    
    app.layout = html.Div(
        dbc.Container(
            du.Upload(
                id='uploader',
                text='点击或拖动文件到此进行上传!',
                text_completed='已完成上传文件:',
                cancel_button=True,
                pause_button=True,
                filetypes=['md', 'mp4'],
                default_style={
                    'background-color': '#fafafa',
                    'font-weight': 'bold'
                },
                upload_id='我的上传'
            )
        )
    )
    
    if __name__ == '__main__':
        app.run_server(debug=True)

    但像前面的例子那样直接在定义app.layout时就传入实际的du.Upload()部件,会产生一个问题——应用启动后,任何访问应用的用户都对应一样的upload_id,这显然不是我们期望的,因为不同用户的上传文件会混在一起。

    因此可以参考下面例子的方式,在每位用户访问时再渲染随机id的上传部件,从而确保唯一性:

    app3.py

    import dash
    import dash_uploader as du
    import dash_bootstrap_components as dbc
    import dash_html_components as html
    
    import uuid
    
    app = dash.Dash(__name__)
    
    # 配置上传文件夹
    du.configure_upload(app, folder='temp')
    
    def render_random_id_uploader():
    
        return du.Upload(
                id='uploader',
                text='点击或拖动文件到此进行上传!',
                text_completed='已完成上传文件:',
                cancel_button=True,
                pause_button=True,
                filetypes=['md', 'mp4'],
                default_style={
                    'background-color': '#fafafa',
                    'font-weight': 'bold'
                },
                upload_id=uuid.uuid1()
            )
    
    def render_layout():
    
        return html.Div(
        dbc.Container(
            render_random_id_uploader()
        )
    )
    
    app.layout = render_layout
    
    if __name__ == '__main__':
        app.run_server(debug=True)

    可以看到,每次访问时由于upload_id不同,因此不同的会话拥有了不同的子目录。

    2.1.3 配合du.Upload()进行回调

    在du.Upload()中额外还有isCompleted与fileNames两个属性,前者用于判断当前文件是否上传完成,后者则对应此次上传的文件名称,参考下面这个简单的例子:

    app4.py

    import dash
    import dash_uploader as du
    import dash_bootstrap_components as dbc
    import dash_html_components as html
    from dash.dependencies import Input, Output, State
    
    app = dash.Dash(__name__)
    
    # 配置上传文件夹
    du.configure_upload(app, folder='temp')
    
    app.layout = html.Div(
        dbc.Container(
            [
                du.Upload(id='uploader'),
                html.H5('上传中或还未上传文件!', id='upload_status')
            ]
        )
    )
    
    
    @app.callback(
        Output('upload_status', 'children'),
        Input('uploader', 'isCompleted'),
        State('uploader', 'fileNames')
    )
    def show_upload_status(isCompleted, fileNames):
        if isCompleted:
            return '已完成上传:'+fileNames[0]
    
        return dash.no_update
    
    
    if __name__ == '__main__':
        app.run_server(debug=True, port=8051)

    2.2 配合flask进行文件下载

    相较于文件上传,在Dash中进行文件的下载就简单得多,因为我们可以配合flask的send_from_directory以及html.A()部件来为指定的服务器端文件创建下载链接,譬如下面的简单示例就打通了文件的上传与下载:

    app5.py

    from flask import send_from_directory
    import dash
    import dash_uploader as du
    import dash_html_components as html
    import dash_bootstrap_components as dbc
    from dash.dependencies import Input, Output
    import os
    
    app = dash.Dash(__name__)
    
    du.configure_upload(app, 'temp', use_upload_id=False)
    
    app.layout = html.Div(
        dbc.Container(
            [
                du.Upload(id='upload'),
                html.Div(
                    id='download-files'
                )
            ]
        )
    )
    
    @app.server.route('/download/file>')
    def download(file):
    
        return send_from_directory('temp', file)
    
    @app.callback(
        Output('download-files', 'children'),
        Input('upload', 'isCompleted')
    )
    def render_download_url(isCompleted):
    
        if isCompleted:
            return html.Ul(
                [
                    html.Li(html.A(f'/{file}', href=f'/download/{file}', target='_blank'))
                    for file in os.listdir('temp')
                ]
            )
    
        return dash.no_update
    
    if __name__ == '__main__':
        app.run_server(debug=True)

    3 用Dash编写简易个人网盘应用

    在学习了今天的案例之后,我们就掌握了如何在Dash中开发文件上传及下载功能,下面我们按照惯例,结合今天的主要内容,来编写一个实际的案例;

    今天我们要编写的是一个简单的个人网盘应用,我们可以通过浏览器访问它,进行文件的上传、下载以及删除:

    import dash
    import dash_bootstrap_components as dbc
    import dash_html_components as html
    from dash.dependencies import Input, Output, State
    import dash_uploader as du
    import os
    from flask import send_from_directory
    import time
    
    app = dash.Dash(__name__, suppress_callback_exceptions=True)
    
    du.configure_upload(app, 'NetDisk', use_upload_id=False)
    
    app.layout = html.Div(
        dbc.Container(
            [
                html.H3('简易的个人云盘应用'),
                html.Hr(),
                html.P('文件上传区:'),
                du.Upload(id='upload',
                          text='点击或拖动文件到此进行上传!',
                          text_completed='已完成上传文件:',
                          max_files=1000),
                html.Hr(),
                dbc.Row(
                    [
                        dbc.Button('删除选中的文件', id='delete-btn', outline=True),
                        dbc.Button('打包下载选中的文件', id='download-btn', outline=True)
                    ]
                ),
                html.Hr(),
                dbc.Spinner(
                    dbc.Checklist(
                        id='file-list-check'
                    )
                ),
                html.A(id='download-url', target='_blank')
            ]
        )
    )
    
    
    @app.server.route('/download/file>')
    def download(file):
        return send_from_directory('NetDisk', file)
    
    
    @app.callback(
        [Output('file-list-check', 'options'),
         Output('download-url', 'children'),
         Output('download-url', 'href')],
        [Input('upload', 'isCompleted'),
         Input('delete-btn', 'n_clicks'),
         Input('download-btn', 'n_clicks')],
        State('file-list-check', 'value')
    )
    def render_file_list(isCompleted, delete_n_clicks, download_n_clicks, check_value):
        # 获取上下文信息
        ctx = dash.callback_context
    
        if ctx.triggered[0]['prop_id'] == 'delete-btn.n_clicks':
    
            for file in check_value:
                try:
                    os.remove(os.path.join('NetDisk', file))
                except FileNotFoundError:
                    pass
    
        if ctx.triggered[0]['prop_id'] == 'download-btn.n_clicks':
    
            import zipfile
    
            with zipfile.ZipFile('NetDisk/打包下载.zip', 'w') as zipobj:
                for file in check_value:
                    try:
                        zipobj.write(os.path.join('NetDisk', file))
                    except FileNotFoundError:
                        pass
    
            return [
                       {'label': file, 'value': file}
                       for file in os.listdir('NetDisk')
                       if file != '打包下载.zip'
                   ], '打包下载链接', '/download/打包下载.zip'
    
        time.sleep(2)
    
        return [
                   {'label': file, 'value': file}
                   for file in os.listdir('NetDisk')
                   if file != '打包下载.zip'
               ], '', ''
    
    
    if __name__ == '__main__':
        app.run_server(debug=True)

    以上就是90行Python代码开发个人云盘应用的详细内容,更多关于python 开发个人云盘的资料请关注脚本之家其它相关文章!

    您可能感兴趣的文章:
    • python 实现百度网盘非会员上传超过500个文件的方法
    • Python 一键获取百度网盘提取码的方法
    • Python使用百度API上传文件到百度网盘代码分享
    • Python实现115网盘自动下载的方法
    • Python解析网页源代码中的115网盘链接实例
    上一篇:基于python实现银行管理系统
    下一篇:基于python的matplotlib制作双Y轴图
  • 相关文章
  • 

    © 2016-2020 巨人网络通讯 版权所有

    《增值电信业务经营许可证》 苏ICP备15040257号-8

    90行Python代码开发个人云盘应用 90行,Python,代码,开发,个,