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:10px
padding-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 error
allowedFileExtensions: ['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 error
allowedFileExtensions: ['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, //上传文件最大值,单位kb
uploadAsync: 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,redirect
app = 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 + filename
if 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 + filename
print(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