上篇文章【Flask项目】文件分享系统(二)中介绍了如何读取目录内容和下载文件,这篇继续讲上传文件和HTML模板。
上传文件
上传文件即用户在浏览器上选择要上传的文件,然后调用上传接口把文件传到flask程序,在看代码前,要先了解一个知识点,那就是请求,什么是请求呢?
请求就是浏览器向flask程序发起访问,告诉flask程序,我想要认识你,flask程序说好呀,欢迎你来和我交流,但是你得和我用同样的语言交流,不然我听不懂。就这样,浏览器必须使用GET、POST、PUT、DELETE等方法和flask程序进行交流,而其中常用的方法就是GET和POST。这里GET和POST方法的区别不做过多讲解了,大家可以看我写的相关文章或去度娘一下,当然,要想快速检索可以考虑AI搜索。这里大家简单的理解为GET只能携带有限的明文参数访问flask程序,而POST可以以非明文的方式携带的内容更多。
当然请求中不光有请求方法,还包括URL、请求头等一些内容,想详细了解的,可以给我留言,我会整理出来一篇详细的文章讲解。简单了解了请求后,我们可以知道,上传文件可以使用POST的方法,携带的数据量大,确相对GET安全一些。
再回到flask程序中,我们如何让其支持POST?又如何从请求中拿到文件内容呢?这个后面来讲,先来看下上传文件的代码。
@app.route('/upload/', methods=['GET', 'POST'])
def upload():
if request.method == 'POST':
file = request.files['file']
if file:
filename = secure_filename(file.filename)
print(filename)
if os.path.exists(rootdir + 'data' + os.sep + filename):
filename = str(int(time.time())) + '_' + filename
file.save(os.path.join(rootdir + 'data', filename))
return('文件上传成功')
else:
return('报错啦!!!!')
从上面的代码可以看到,定义路由的地方@app.route('/upload/', methods=['GET', 'POST'])
,我们加了个参数methods,这个参数就是指定访问该路由可以使用的方法嘀。
我们还可能看到,上传的视图函数中,我们用到了request,英文好的同学应该能知道,这个词有请求的意思,没错这个就是获取浏览器发来的请求嘀。request可不是我们自己定义的变量,而是flask中自带的全局变量,使用from flask import request
来导入这个函数。
后面的代码就是判断当前文件是否存在的,如果存在则给他文件名上加个时间,如果不存在则直接保存这个文件。这里为了保证文件名的合法性我使用了werkzeug中的secure_filename函数,使用from werkzeug.utils import secure_filename
来导入,这个函数可以保证文件名中不会有特殊字符,造成保存文件失败。
html模板
到此我们只实现了后端的内容,还需要前端页面才能正常使用,因为我们对前端页面不做要求,所以我们只需要简单的把内容显示出来即可,以下是前端代码。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>文件共享</title>
<style>
html {
font-family: sans-serif;
}
body {
max-width: 80%;
margin: 20px auto;
}
header {
font-size: 50px;
font-weight: 1000;
text-align: center;
}
main {
max-width: 100%;
}
p {
font-size: 16px;
font-weight: 800;
}
div {
width: fit-content;
display: inline-flex;
align-content: flex-start;
flex-wrap: wrap;
flex-shrink: 2;
}
form {
width: fit-content;
margin-top: 25px;
border: 2px solid royalblue;
}
ul {
list-style-type: none;
}
a:hover {
color: red;
}
input:hover {
background-color: greenyellow;
}
</style>
</head>
<body>
<header>文件共享系统</header>
<main>
<p>
当前路径:{% if currentpath %} {{ currentpath }} <a href="../">(点这返回上一级)</a> {% else %} root {% endif %}
</p>
<div>
<ul id="filelist">
{% for dir in dirlist %}
<li style="height:25px"><a href="{{ dir }}">{{ dir }}</a><span style="color:gray;font-size:10px"> 目录<span></li>
{% endfor %}
{% for file in filelist %}
<li style="height:25px"><a href="{{ file['name'] }}">{{ file['name'] }}</a><span style="color:gray"> ({{ file['size'] }})<span></li>
{% endfor %}
</ul>
</div>
<form action="#" id="uploadForm" method="post" enctype="multipart/form-data">
<input type="file" id="fileInput" name="file" accept="*/*" onchange="isFileSelected()" />
<input type="submit" id="fileupload" value="上传" disabled/>
</form>
</main>
<script>
// 判断文件是否选择
function isFileSelected() {
var fileInput = document.getElementById('fileInput'); // 获取文件选择控件的id
var fileupload = document.getElementById('fileupload'); // 获取上传控件的id
if (fileInput.value) {
fileupload.removeAttribute("disabled");
} else {
fileupload.setAttribute("disabled", "disabled");
}
}
// 提交表单,并以提示框的方式显示返回结果
const form = document.getElementById('uploadForm');
form.addEventListener('submit', function(event) {
event.preventDefault();
var formData = new FormData(form);
fetch('/upload/', {
method: 'POST',
body: formData
}).then(response => response.text())
.then(data => {
alert(data);
window.location.reload();
})
})
</script>
</body>
</html>
我们在读取目录内容部分用了render_template来渲染模板,使用了这个方法,我们就可以在html中使用一些特定的关键字来使用后端传来的变量了。
我使用了{% if currentpath %} {{ currentpath }} <a href="../">(点这返回上一级)</a> {% else %} root {% endif %}
来判断当前的显示路径,如果是根目录data就显示为root,如果在data下面的子目录中,则显示实际路径。还是用了两个for循环{% for dir in dirlist %}...{% endfor %}
列出文件夹和文件。
然后使用了一个form表单实现选择文件和上传,并且使用JS脚本控制上传按钮的可用,如果选择文件的控件有文件,则上传按钮可用,若没有选中文件,上传按钮则不可用。
此外,还在JS脚本中实现了上传文件功能,并将结果返回到JS的alert警告框中。
到此整个文件分享系统就介绍完了,最后在flask程序中加上以下代码,让程序能在脚本中运行。
if __name__ == "__main__":
app.run(host='0.0.0.0',debug=False)
然后使用python share.py
即可运行程序。
效果
编写过程介绍完了,下面来看看实际效果
访问主页的效果
上传成功的提示框
目录和文件的显示效果
如果想直接要源码的话,可关注我的公众号回复关键词【flask文件分享系统】获取