Flask boostrap实现图片视频上传下载展示
- 1、展示效果
- 2、前端代码
- 3、后端代码
1、展示效果
项目目录结构
2、前端代码
html
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>Title</title><!--<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@5.2.0/dist/css/bootstrap.min.css" crossorigin="anonymous"><link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.5.0/font/bootstrap-icons.min.css" crossorigin="anonymous"><link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.15.4/css/all.css" crossorigin="anonymous"><script src="https://code.jquery.com/jquery-3.6.0.min.js" crossorigin="anonymous"></script><script src="https://cdn.jsdelivr.net/npm/bootstrap@5.2.0/dist/js/bootstrap.bundle.min.js" crossorigin="anonymous"></script>--><!-- 国内的,预览有些按钮用不了 新 Bootstrap5 核心 CSS 文件 -->
<link rel="stylesheet" href="https://cdn.staticfile.org/twitter-bootstrap/5.1.1/css/bootstrap.min.css">
<!-- 最新的 Bootstrap5 核心 JavaScript 文件 -->
<script src="https://cdn.staticfile.org/twitter-bootstrap/5.1.1/js/bootstrap.bundle.min.js"></script><link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.15.4/css/all.css" crossorigin="anonymous"><script src="https://code.jquery.com/jquery-3.6.0.min.js" crossorigin="anonymous"></script><link href="../static/fileinput/css/fileinput.css" media="all" rel="stylesheet" type="text/css"/><link href="../static/fileinput/themes/explorer-fa5/theme.css" media="all" rel="stylesheet" type="text/css"/><script src="../static/fileinput/js/plugins/buffer.min.js" type="text/javascript"></script><script src="../static/fileinput/js/plugins/filetype.min.js" type="text/javascript"></script><script src="../static/fileinput/js/plugins/piexif.js" type="text/javascript"></script><script src="../static/fileinput/js/plugins/sortable.js" type="text/javascript"></script><script src="../static/fileinput/js/fileinput.js" type="text/javascript"></script><script src="../static/fileinput/js/locales/fr.js" type="text/javascript"></script><script src="../static/fileinput/js/locales/es.js" type="text/javascript"></script><script src="../static/fileinput/themes/fa5/theme.js" type="text/javascript"></script><script src="../static/fileinput/themes/explorer-fa5/theme.js" type="text/javascript"></script><script src="../static/js/imgEnlarge.js"></script><style>/*统配设置整个文件为宋体,12号字*/*{font-family: '楷体';font-size:12px;}/*设置商品列表宽度占浏览器60%,居中*/#main {width:90%;height: 600px;margin: 0 auto;border:0px solid green;}#main2 {width:90%;height: 600px;margin: 0 auto;border:0px solid green;}/*设置图片宽高*/img {width: 140px;height: 200px;padding: 25px 25px 0px 25px;}/*设置图片宽高*/video {width: 300px;height: 220px;padding: 10px 10px 0px 10px;}.myvideobord {width:330px;height: 260px;border: 2px solid green;border-radius:10px;/*设置圆角矩形*/margin-left: 5px;margin-bottom: 20px;/*边框上下距离*/margin-right: 5px;}/*设置图片边框*/.sfz_01_34 {width:200px;height: 250px;border: 2px solid green;border-radius:10px;/*设置圆角矩形*/margin-left: 5px;margin-bottom: 20px;/*边框上下距离*/margin-right: 5px;}.sfz_02_34{color: red;text-align: center;}.sfz_03_34{height: 60px;color:black;text-indent: 2em;}/*设置加入购物单*/.sfz_04_34{margin-left:20px;padding-top:10pxpadding-bottom:10px;text-align: center;font-size: 10px;border-radius:0px;color: white;width: 30%;line-height: 20px;background: red;float: left;}.sfz_05_34{margin-right: 20px;/*靠边框距离*/color: white;font-size: 10px;width: 30%;height: 20px;line-height: 20px;/*字在中间*/text-align: center;background: greenyellow;float: right;}/*去掉列表序号去掉*/ul {list-style: none;overflow: hidden;}/*设置左浮动*/ul li {float: left;}/*设置默认状态是黑色字体*/a:link {color: black;}/*设置鼠标放上去后显示红色*/div:hover {border-color: #ff0000;}{#.qqq{#}{# transition: all 0.2s linear;#}{#}#}{##}{#.qqq:hover{#}{# transform: scale(1.8);#}{# transition: all 0.2s linear;#}{#}#}</style>
<!--<script src="static/js/jquery-3.3.1.min.js"></script>--><script>$(document).ready(function(){$("button").click(function(){$("p").hide();});
});
</script></head>
<body class="container my-4"><br> <br> <br><div class="container" style=" padding: 10px 3ex 2em 1cm; border: 2px solid blue;width: 70%;height: 100%"><hr><p align="center" style="color:sienna;font-size:30px" >上传表单</p><hr><form action="/" method="post" class="form-horizontal" role="form" enctype="multipart/form-data" ><div class="form-group"><label for="name" class="control-label col-md-4">用户名</label><div class="col-md-4"><input type="text" id="name" name="name" class="form-control" placeholder="请输入用户名"></div></div><div class="form-group"><label for="pwd" class="control-label col-md-4">密码</label><div class="col-md-4"><input type="text" class="form-control" id="pwd" name="password" placeholder="请输入密码"></div></div><div class="form-group"><label class="control-label col-md-4" >性别</label><div class="col-md-4"><label class="radio-inline" for="male"><input type="radio" name="sex" id="male" >男</label><label class="radio-inline" for="female"><input type="radio" name="sex" id="female"checked>女</label></div></div><div class="form-group"><label for="" class="control-label col-md-4">兴趣爱好</label><div class="col-md-4"><label for="qin" class="checkbox-inline"><input type="checkbox" name="" id="qin">琴</label><label for="qi" class="checkbox-inline"><input type="checkbox" name="" id="qi">棋</label><label for="shu" class="checkbox-inline"><input type="checkbox" name="" id="shu">书</label><label for="hua" class="checkbox-inline"><input type="checkbox" name="" id="hua" checked>画</label></div></div><div class="form-group"><label for="" class="control-label col-md-4">所在地</label><div class="col-md-4"><select name="adree" id="" class="form-control"><option value="">湖北</option><option value="">湖南</option><option value="">河北</option><option value="" selected>河南</option></select></div></div><div class="form-group"><div class="file-loading"><input id="file-1" name="video" type="file" multiple class="file" data-overwrite-initial="false" data-min-file-count="1" data-browse-on-zone-click="true"></div></div><div class="form-group"><div class="file-loading"><input id="file-2" name="image" type="file" multiple class="file" data-overwrite-initial="false" data-min-file-count="2" data-browse-on-zone-click="true"></div></div><div class="form-group"><button type="submit" class="btn btn-primary">Submit</button><button type="reset" class="btn btn-outline-secondary">Reset</button></div></form><br> <br> <br> <br></div><hr>
<br>
<hr><div class="container"><hr>
<p align="center" style="color:sienna;font-size:30px" >图像展示</p>
<hr><ul><!-- <li><div class="sfz_01_34"><img src="p30.png"><p class="sfz_02_34">¥3998.00</p><p class="sfz_03_34">p30 超感光麒麟980AL智能芯片全面屏屏内指纹版手机8G+128GB全网通4G手机</p><p class="sfz_04_34">加入购物车</p><p class="sfz_05_34">立即购买</p></div></li><li><div class="sfz_01_34"><img src="../static/hua.jpg"><a class="sfz_05_34" href="url">链接文本</a></div></li>-->{% for value in imglist %}<li><div class="sfz_01_34"><img class="qqq" src="./static/myfile/img/{{ value }}"><a class="sfz_04_34" href="/delete/img/{{ value }}/">删除</a><a class="sfz_05_34" href="/down/img/{{ value }}/">下载</a></div></li>{% endfor %}</ul>
</div>
<hr>
<br>
<hr>
<div class="container"><hr><p align="center" style="color:sienna;font-size:30px" >视频展示</p><hr><ul><!-- <li><div class="sfz_01_34"><img src="p30.png"><p class="sfz_02_34">¥3998.00</p><p class="sfz_03_34">p30 超感光麒麟980AL智能芯片全面屏屏内指纹版手机8G+128GB全网通4G手机</p><p class="sfz_04_34">加入购物车</p><p class="sfz_05_34">立即购买</p></div></li><li><div class="myvideobord"><video width="320" height="240" controls autoplay><source src="../static/myfile/video/12s.mp4" type="video/mp4"><source src="../static/myfile/video/12s.ogg" type="video/ogg"><source src="../static/myfile/video/12s.webm" type="video/webm">您的浏览器不支持 video 属性。</video><a class="sfz_04_34" href="#">删除</a><a class="sfz_05_34" href="#">下载</a></div></li>-->{# {% for value in imglist %}#}
{##}
{# <li>#}
{# <div class="sfz_01_34"><img class="qqq" src="./static/myfile/img/{{ value }}">#}
{# <a class="sfz_04_34" href="/delete/{{ value }}/">删除</a>#}
{##}
{# <a class="sfz_05_34" href="/down/{{ value }}/">下载</a>#}
{##}
{# </div>#}
{# </li>#}
{# {% endfor %}#}{% for value in videolist %}<li><div class="myvideobord"><video width="320" height="240" controls autoplay><source src="../static/myfile/video/{{ value }}" type="video/mp4">您的浏览器不支持 video 属性。</video><a class="sfz_04_34" href="/delete/video/{{ value }}">删除</a><a class="sfz_05_34" href="/down/video/{{ value }}/">下载</a></div></li>{% endfor %}<!--<li><div class="myvideobord"><video width="320" height="240" controls autoplay><source src="movie.mp4" type="video/mp4"><source src="movie.ogg" type="video/ogg"><source src="movie.webm" type="video/webm">您的浏览器不支持 video 属性。</video><a class="sfz_04_34" href="#">删除</a><a class="sfz_05_34" href="#">下载</a></div></li><li><div class="myvideobord"><video width="320" height="240" controls autoplay><source src="movie.mp4" type="video/mp4"><source src="movie.ogg" type="video/ogg"><source src="movie.webm" type="video/webm">您的浏览器不支持 video 属性。</video><a class="sfz_04_34" href="#">删除</a><a class="sfz_05_34" href="#">下载</a></div></li><li><div class="myvideobord"><video width="320" height="240" controls autoplay><source src="movie.mp4" type="video/mp4"><source src="movie.ogg" type="video/ogg"><source src="movie.webm" type="video/webm">您的浏览器不支持 video 属性。</video><a class="sfz_04_34" href="#">删除</a><a class="sfz_05_34" href="#">下载</a></div></li><li><div class="myvideobord"><video width="320" height="240" controls autoplay><source src="movie.mp4" type="video/mp4"><source src="movie.ogg" type="video/ogg"><source src="movie.webm" type="video/webm">您的浏览器不支持 video 属性。</video><a class="sfz_04_34" href="#">删除</a><a class="sfz_05_34" href="#">下载</a></div></li><li><div class="myvideobord"><video width="320" height="240" controls autoplay><source src="movie.mp4" type="video/mp4"><source src="movie.ogg" type="video/ogg"><source src="movie.webm" type="video/webm">您的浏览器不支持 video 属性。</video><a class="sfz_04_34" href="#">删除</a><a class="sfz_05_34" href="#">下载</a></div></li><li><div class="myvideobord"><video width="320" height="240" controls autoplay><source src="movie.mp4" type="video/mp4"><source src="movie.ogg" type="video/ogg"><source src="movie.webm" type="video/webm">您的浏览器不支持 video 属性。</video><a class="sfz_04_34" href="#">删除</a><a class="sfz_05_34" href="#">下载</a></div></li>--></ul>
</div><script>$("#file-0").fileinput({theme: 'fa5',uploadUrl: '#',overwriteInitial: false,}).on('filepreupload', function(event, data, previewId, index) {alert('The description entered is:\n\n' + ($('#description').val() || ' NULL'));});$("#file-1").fileinput({language: 'zh', //设置语言dropZoneEnabled: true, //是否显示拖拽区域dropZoneTitle: "视频拖放到这里", //拖拽区域显示文字theme: 'fa5',uploadUrl: '#', // you must set a valid URL here else you will get an errorallowedFileExtensions: ['mp4'],overwriteInitial: false,showUpload: false, //是否显示上传按钮maxFileSize: 9000,maxFilesNum: 100,//allowedFileTypes: ['image', 'video', 'flash'],});$("#file-2").fileinput({language: 'zh', //设置语言dropZoneEnabled: true, //是否显示拖拽区域dropZoneTitle: "图片拖放到这里", //拖拽区域显示文字theme: 'fa5',uploadUrl: '#', // you must set a valid URL here else you will get an errorallowedFileExtensions: ['jpg', 'png', 'gif'],overwriteInitial: false,showUpload: false, //是否显示上传按钮maxFileSize: 9000,maxFilesNum: 100,// minFileCount: 1,//allowedFileTypes: ['image', 'video', 'flash'],/*slugCallback: function (filename) {return filename.replace('(', '_').replace(']', '_');} */});/*$('#file').fileinput({language: 'zh', //设置语言dropZoneEnabled: true, //是否显示拖拽区域dropZoneTitle: "可以将图片拖放到这里", //拖拽区域显示文字uploadUrl: 'file/imgSave', //上传路径allowedFileExtensions: ['jpg', 'png', 'gif', 'jpeg'], //指定上传文件类型maxFileSize: 0,maxFileSize: 2048, //上传文件最大值,单位kbuploadAsync: true, //异步上传maxFileCount: 2 //上传文件最大个数。}).on("fileuploaded", function(event,data) { //异步上传成功后回调console.log(data); //data为返回的数据});
*/</script></body>
</html>
js代码
fileinput插件下载地址:https://github.com/kartik-v/bootstrap-fileinput/
imgEnlarge.js如下
// 依赖jq 默认点击<img>标签就会放大,可根据自己情况修改$(document).ready(function () {$("body").append("<!--放大图片-->\n" +"<div class=\"blackScreen\" style=\"display: none;display:none; position:fixed; top:0; right:0; bottom:0; left:0; background-color:#000000; z-index:1000;\">\n" +" <span class=\"fullScreenImg\" style='position:absolute; top:0; right:0; bottom:60px; left:0; background:center center no-repeat; background-size:contain;'></span>\n" +"</div>");
});$(function () {// 放大图片$('img').on('click', function () {// console.log("放大");if (this.getAttribute("src") != "url(\"null\") 0% 0% / 100% no-repeat") {$(".fullScreenImg").css("background-image", "url(\"" + this.getAttribute("src") + "\")");$(".blackScreen").fadeIn(100);}});// 关闭放大图片$(".blackScreen").on("click", function () {// console.log("关闭");$(".blackScreen").fadeOut(100);});});
3、后端代码
# from flask import Flask, render_template
# from flask import request, url_for, redirect, flash
import os
import uuid
from flask import Flask, render_template,send_from_directory, url_for, request,jsonify,redirectapp = Flask(__name__)@app.route('/', methods=['GET', 'POST'])
def mulfileupload():path_imgs = 'static/myfile'imglist = os.listdir(path_imgs+'/img')videolist=os.listdir(path_imgs+'/video')# path_video=print(imglist)if request.method == 'POST':print(request.headers)# print(request.json)print(request.headers.get("content_type"))print("values:", request.values)print("files:", request.files)print('form:', request.form)print('data:', request.data)# 获取数据并转化成字典user_info = request.form.to_dict()print(user_info)# 使用request模块接收带对应标签的文件列表,这里对应图片和视频image_files = request.files.getlist('image')video_files = request.files.getlist('video')print(image_files,video_files)# 判断是否有空文件if not image_files and not video_files:print("文件上传为空")return jsonify({"code": -1,"message": "No upload images or videos."})if image_files[0].filename and video_files[0].filename:# 从文件列表依次取出并保存,文件名与上传时一致for image_file in image_files:print('./static/myfile/img/' + image_file.filename)image_file.save('./static/myfile/img/'+image_file.filename)# 同上for video_file in video_files:print('./static/myfile/video/'+video_file.filename)video_file.save('./static/myfile/video/'+video_file.filename)imglist = os.listdir(path_imgs+'/img')videolist = os.listdir(path_imgs + '/video')return render_template('boostrapfrom.html', msg='文件上传成功',imglist=imglist,videolist=videolist)else:return render_template('boostrapfrom.html',imglist=imglist,videolist=videolist)@app.route('/down/<filetype>/<filename>/')
def down(filetype,filename):dir = os.getcwd() + os.sep + 'static/myfile/' + filetype + '/'# dir = os.getcwd() + os.sep + 'static/myfile/img/'print(dir + filename)# 下载图片设置return send_from_directory(dir, filename, as_attachment=True)@app.route('/delete/<filetype>/<filename>/')
def delete(filetype,filename):dir = os.getcwd() + os.sep + 'static/myfile/' + filetype + '/'# dir = os.getcwd() + os.sep + 'static/myfile/img/'print(dir + filename)# file_name = "D:/Python_GJ/AAA/1 (1).png" # '../' + list1[i]file_name=dir + filenameif os.path.exists(file_name):os.remove(file_name)print('成功删除文件:', file_name)else:print('未找到此文件:', file_name)# 函数的名字return redirect(url_for('mulfileupload'))@app.route('/test/<filetype>/<filename>')
def test(filetype,filename):dir = os.getcwd() + os.sep + 'static/'+filetype+'/'print('filetype:',filetype)print('filename',filename)print(dir + filename)# file_name = "D:/Python_GJ/AAA/1 (1).png" # '../' + list1[i]file_name=dir + filenameprint(file_name)# if os.path.exists(file_name):# os.remove(file_name)# print('成功删除文件:', file_name)# else:# print('未找到此文件:', file_name)# 函数的名字return redirect(url_for('mulfileupload'))if __name__ == '__main__':# app.run(debug=True)# app.run(debug=True, host='127.0.0.1', port=5003)app.run(debug=True,host='0.0.0.0',port=8080)
代码下载链接:https://download.csdn.net/download/weixin_44986037/87986647