本文分享知识:

  1. element 中上传组件 upload 的使用方法
  2. table 表格组件、form 表单组件、tooltip 提示框组件
  3. Python 中 os 模块的使用
  4. flask 接受前端传递的文件
  5. pyinstaller 打包 flask 项目

项目源码地址:https://gitee.com/myrensheng/encryption

加密文件比加密字符串更加复杂。

一、前端

页面的布局如下:

第一行为文件上传区,以及显示上传数据的表格。

第二行为加密的选项,以及加密后的数据表格。

1.1 上传文件

<el-upload class="upload-demo" drag :multiple=false :show-file-list=false
:on-success="GetTableDate" action="http://127.0.0.1:5000/upload" multiple>
<i class="el-icon-upload"></i>
<div class="el-upload__text">只能上传excel文件;
<br>将文件拖到此处,或<em>点击上传</em>
</div>
<div class="el-upload__tip" slot="tip"></div>
</el-upload>

el-upload 文件上传组件

on-success 方法,文件上传完成后,调用 GetTableDate 方法

action=“http://127.0.0.1:5000/upload” 上传的地址

1.2 数据表格

<el-table :data="tableData" max-height="250" border style="width: 100%">
<el-table-column type="index" :index="indexMethod"></el-table-column>
<el-table-column v-for="i in tableCols" :prop="i+''" :label="i+''">
</el-table-column>
</el-table>

data:显示的数据

el-table-column type=“index” :index=“indexMethod” 显示表格索引

prop 属性,对应列内容的字段名

label 显示的标题

1.3 加密选项

表单组件

<el-form label-width="80px" :model="ruleForm" :rules="rules" ref="ruleForm">
<el-form-item label="" prop=""> </el-form-item>
</el-form>

model 表单数据对象

rules 表单验证规则

加密内容输入框

考虑到各种不可预测的因素,以及完成加密多列的功能。这里将加密列全部用 1,2,3,4… 数字表示。即:1 表示第一列,输入的数字用英文逗号(,)隔开。

<el-form-item label="加密列" prop="encryCols">
<el-input v-model="ruleForm.encryCols"></el-input>
</el-form-item>

el-input 输入框组件

v-model 输入的内容赋值给 ruleForm.encryCols

加密算法选择框

加密算法有很多中,用一个下拉框组件搞定

<el-form-item label="加密算法">
<el-select v-model="ruleForm.encryModel" placeholder="请选择加密算法">
<el-option label="md5_32" value="md5_32"></el-option>
<el-option label="md5_16" value="md5_16"></el-option>
<el-option label="sha1" value="sha1"></el-option>
<el-option label="sha224" value="sha224"></el-option>
<el-option label="sha256" value="sha256"></el-option>
<el-option label="sha512" value="sha512"></el-option>
</el-select>
</el-form-item>

el-select下拉框组件

el-option 下拉框中的选项

v-model=“ruleForm.encryModel” 将 el-option 中的 value 值绑定到ruleForm中的 encryModel 变量中

大小写单选框

加密后的字符串可以是大写也可以是小写

<el-form-item label="大写小写">
<el-radio-group v-model="ruleForm.encryStyle">
<el-radio label="小写"></el-radio>
<el-radio label="大写"></el-radio>
</el-radio-group>
</el-form-item>

el-radio-group 单选框

el-radio 单选框中的选项

提交、重置按钮

为防止后端接口请求过于频繁,当没有上传数据时,不请求数据。

重置按钮作用:清空输入框、回复初始化的选项

<el-form-item>
<el-button type="primary" v-if="tableData" @click="submitForm('ruleForm')">
提交
</el-button>
<el-tooltip class="item" v-else effect="dark" content="未上传Excel文件"
placement="top-start">
<el-button type="danger">提交</el-button>
</el-tooltip>
<el-button @click="resetForm('ruleForm')">重置</el-button>
</el-form-item>

用 v-if 、v-else 判断按钮是否需要调用函数

1.4 加密数据

加密数据表格中只显示输入的加密列,以及加密后的数据。

<el-table :data="md5TableData" max-height="250" border style="width: 100%">
<el-table-column type="index" :index="indexMethod"></el-table-column>
<el-table-column v-for="j in md5TableCols" :prop="j+''" :label="j+''">
</el-table-column>
</el-table>

data:显示的数据

el-table-column type=“index” :index=“indexMethod” 显示表格索引

prop 属性,对应列内容的字段名

label 显示的标题

1.5 下载按钮

当没有加密数据时,下载按钮不请求后端接口。

<a v-if="md5TableData" href="http://127.0.0.1:5000/download">
<el-button type="primary" style="margin-top: 10px;">
下载
</el-button>
</a>
<el-tooltip class="item" v-else effect="dark" content="没有加密文件"
placement="top-start">
<el-button size="small" type="danger" style="margin-top: 10px;">下载</el-button>
</el-tooltip>

用 v-if 、v-else 判断按钮是否需要调用函数

el-tooltip 提示框组件

二、后端

2.1 、upload 文件上传

上传的文件接口,文件保存到同级目录下。当上传新的文件时,需要提前删除之前上传及加密后的文件。

@app.route("/upload", methods=["POST"])
def upload():
# 上传文件到 static/excel 文件夹中
# 清空数据文件
if os.listdir(excel_path):
excel_file = os.path.join(excel_path, os.listdir(excel_path)[0])
os.remove(excel_file)
# 清空已加密的excel文件
if os.listdir(encry_excel_path):
encry_excel_file = os.path.join(encry_excel_path, os.listdir(encry_excel_path)[0])
os.remove(encry_excel_file)
if 'file' not in request.files:
return jsonify({"status": 400, "msg": "请上传excel文件!"})
# 获取文件
file = request.files['file']
if file.filename != '' and allowed_file(file.filename):
# 文件名不为空并且是excel文件
filename = file.filename
file.save(os.path.join(excel_path, filename))
return jsonify({"status": 200, "msg": filename + "保存成功!"})
return jsonify({"status": 400, "msg": "请上传excel文件"})

os.path.join() 拼接文件地址

os.remove() 删除文件夹下的文件

flask 中使用 request.files[‘file’] 获取上传的文件

file.save() 保存文件

2.2 table 数据表格接口

该接口用于返回上传的excel文件的数据

import xlrd
import xlwt def get_table_values(file_path=excel_path):
# 默认加密第一个表中的数据
if os.listdir(file_path):
filename = os.path.join(file_path, os.listdir(file_path)[0])
workbook = xlrd.open_workbook(filename=filename)
table = workbook.sheets()[0]
# 默认返回前5行数据
# table_rows = 5 if table.nrows >= 5 else table.nrows
table_rows = table.nrows
if table_rows == 0:
return {"status": 400, "msg": "excel中没有数据!"}
# 获取数据
row_list = []
for r in range(table_rows):
row_dict = {}
for k, v in enumerate(table.row_values(rowx=r)):
row_dict[str(k + 1)] = v
row_list.append(row_dict)
return {"table_cols": table.ncols, "row_list": row_list, "excel_name": os.listdir(file_path)[0],
"sheet_name": workbook.sheet_names()[0]}
# 没有excel文件或者上传的不是excel文件
return None @app.route("/table", methods=["GET", "POST"])
def table():
excel_values = get_table_values()
# print(excel_values)
if excel_values:
return jsonify({"status": 200, "msg": "获取数据成功!", "excel_values": excel_values})
else:
return jsonify({"status": 400, "msg": "请上传excel文件"})

xlrd.open_workbook() 打开指定的excel文件

workbook.sheets()[0] 表示第一个工作薄

table.nrows 表格的行数

table.row_values() 返回对应行的数据

2.3 encryption 数据加密

用于接受前端传递的加密参数

import hashlib
def encryption_str(string, encry_model="md5_32", encry_style=True):
# 加密为 utf-8 编码
utf_8_str = str(string).encode("utf8")
# 函数字典
param_dict = {
"md5_32": hashlib.md5(utf_8_str),
"md5_16": hashlib.md5(utf_8_str),
"sha1": hashlib.sha1(utf_8_str),
"sha224": hashlib.sha224(utf_8_str),
"sha256": hashlib.sha256(utf_8_str),
"sha512": hashlib.sha512(utf_8_str)
}
encry_result = param_dict[encry_model].hexdigest()
if encry_model == 'md5_16':
encry_result = encry_result[8:-8]
# 返回结果
return encry_result if encry_style == "小写" else encry_result.upper() def encryption_clos(encry_cols=None, encry_model=None, encry_style=None):
# 当加密的是空字符串是不加密,保留空字符串
if not encry_model or not encry_cols or not encry_style:
return None
if os.listdir(excel_path):
filename = os.path.join(excel_path, os.listdir(excel_path)[0])
workbook = xlrd.open_workbook(filename=filename)
table = workbook.sheets()[0]
# excel 中没有数据
if table.ncols == 0:
return "excel 中没有数据!"
if max(encry_cols) - 1 > table.ncols:
# 输入的加密列不在excel中
return str(max(encry_cols)) + "超过excel中最大的列"
# 开始加密数据
encry_workbook = xlwt.Workbook()
work_sheet = encry_workbook.add_sheet("md5加密数据")
c = 0
for col in encry_cols:
r = 0
col_values = table.col_values(colx=col - 1)
work_sheet.write(r, c, str(col))
work_sheet.write(r, c + 1, str(col) + "_" + encry_model + "_" + encry_style)
for v in col_values:
if v == '':
encry_v = v
else:
encry_v = encryption_str(string=v, encry_model=encry_model, encry_style=encry_style)
work_sheet.write(r + 1, c, v)
work_sheet.write(r + 1, c + 1, encry_v)
r += 1
c += 2
encry_file = os.path.join(encry_excel_path, '加密数据.xlsx')
encry_workbook.save(encry_file)
# 返回md5文件的前5行数据
encry_table_info = get_table_values(file_path=encry_excel_path)
return encry_table_info
return "服務器內部錯誤" @app.route("/encryption", methods=["GET", "POST"])
def encryption():
r_json = request.json
encry_content = r_json["encryContent"]
# 加密算法
encry_model = r_json["encryModel"]
# 加密类型(大写、小写)
encry_style = r_json["encryStyle"]
print(encry_content)
if encry_content == "textarea":
encry_textarea = str(r_json["input_textarea"])
res = {
"status": 200,
"output_textarea": encryption_str(encry_textarea, encry_model=encry_model, encry_style=encry_style),
"msg": "加密成功!"
}
return jsonify(res) # 需要加密的列
encry_cols = r_json["encryCols"]
if False in [i.isnumeric() for i in encry_cols.strip().strip(",").split(",")]:
return jsonify({"status": 400, "msg": "加密列以英文‘,’隔开!"})
# 加密成功,直接返回加密后的数据
encry_cols = list(set([int(i) for i in encry_cols.split(",")]))
encry_excel_values = encryption_clos(encry_cols, encry_model, encry_style)
if isinstance(encry_excel_values, dict):
return jsonify({"status": 200, "msg": "加密成功!", "excel_values": encry_excel_values})
else:
return jsonify({"status": 400, "msg": encry_excel_values})

requests.json 获取前端 post 的请求数据

isinstance() 判断变量的数据类型

2.4 download 文件下载

用于下载加密后的文件

@app.route("/download", methods=["GET", "POST"])
def download():
return send_from_directory(encry_excel_path, '加密数据.xlsx')

send_form_directory() 用来发送文件

三、前后端交互

用 axios 库来实现前后端数据交互

<script src="https://unpkg.com/vue/dist/vue.js"></script>
<script src="https://unpkg.com/element-ui/lib/index.js"></script>
<!--导入 axios 获取数据-->
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
<script src="https://cdn.staticfile.org/vue-resource/1.5.1/vue-resource.min.js"></script>
<script>
new Vue({
el: '#app',
delimiters:['[{', '}]'],
data: function() {
return {
FiledsCheckboxGroup: ['上海'],
// EncryRadioGroup: encryptions[0],
tableCols: ["上传数据预览"],
tableData: null,
md5TableCols: ["加密数据预览"],
md5TableData: null,
// excel名字
excel_name: "Excel文件名",
sheet_name: null,
// 表单数据
ruleForm: {
encryCols: '',
encryModel: "md5_32",
encryStyle: '小写',
encryContent:'excel'
},
// 表单验证
rules: {
"encryCols": [{
required: true,
message: '请输入加密列',
trigger: 'blur'
}]
},
// 单字符串加密
output_textarea:null,
textareaEncryForm:{
encryModel: "md5_32",
encryStyle: '小写',
input_textarea:null,
encryContent:'textarea'
},
}
},
methods: {
async GetTableDate(response, file, fileList) {
// 获取上传excel的数据并展示
const {
data: res
} = await this.$http.get("http://127.0.0.1:5000/table")
if (res.status != 200) {
this.$message({
showClose: true,
message: res.msg,
center: true,
type: 'error'
})
this.tableCols = ["数据预览,暂无数据"]
this.tableData = []
} else {
this.$message({
showClose: true,
message: res.msg,
center: true,
type: 'success'
})
this.tableCols = res.excel_values.table_cols
this.tableData = res.excel_values.row_list
this.excel_name = res.excel_values.excel_name
this.sheet_name = res.excel_values.sheet_name
}
},
submitForm(formName) {
this.$refs[formName].validate(async (valid) => {
if (valid) {
// 提交需要加密的列
const {
data: res
} = await this.$http.post("http://127.0.0.1:5000/encryption", this.ruleForm)
if (res.status == 200) {
this.$message({
showClose: true,
message: res.msg,
center: true,
type: 'success'
});
this.md5TableCols = res.excel_values.table_cols;
this.md5TableData = res.excel_values.row_list;
} else {
this.$message({
showClose: true,
message: res.msg,
center: true,
type: 'error'
})
}
} else {
this.$message({
showClose: true,
message: "请输入需要加密的列!",
center: true,
type: 'error'
})
return false;
}
});
},
resetForm(formName) {
this.ruleForm.encryModel = "md5_32";
this.ruleForm.encryCols = "";
this.ruleForm.encryStyle = "小写";
this.$refs[formName].resetFields();
},
indexMethod(index) {
return index;
},
async textareasubmitForm(textareaEncryForm) {
const {data: res} = await this.$http.post("http://127.0.0.1:5000/encryption", this.textareaEncryForm)
if (res.status == 200) {
this.$message({
showClose: true,
message: res.msg,
center: true,
type: 'success'
});
console.log(res);
this.output_textarea = res.output_textarea;
} else {
this.$message({
showClose: true,
message: res.msg,
center: true,
type: 'error'
})
}
},
textarearesetForm() {
this.textareaEncryForm.encryModel = "md5_32";
this.textareaEncryForm.input_textarea = null;
this.textareaEncryForm.encryStyle = "小写";
this.output_textarea = null;
},
},
})
</script>

四、打包exe文件

终于,小凡完成了加密excel文件的事情,考虑到经理和其他需要使用的同事没有Python环境,于是,小凡用 Python中的 pyinstaller 工具,将代码打包为 exe 文件。

pyinstaller -F --add-data="./static;./static" --add-data="./templates;./templates" --add-data="./tools.py;." app.py

flask、element、vue项目实战:搭建一个加密excel数据的网站的更多相关文章

  1. webpack+vue项目实战(四,前端与后端的数据交互和前端展示数据)

    地址:https://segmentfault.com/a/1190000010063757 1.前言 今天要做的,就是在上一篇文章的基础上,进行功能页面的开发.简单点说呢,就是与后端的数据交互和怎么 ...

  2. vue项目实战

    本篇文章主要介绍了vue的环境配置,vue项目的目录结构以及在开发vue项目中问题的一些解决方案. 环境配置及目录结构 1.安装node.js(http://www.runoob.com/nodejs ...

  3. vue项目实战, webpack 配置流程记录

    vue项目实战记录,地址在这 购物车单界面 npm install npm run dev 跑起来可以看到界面效果 这里简单记录一下webpack的编译流程 入口 package.json " ...

  4. vue项目环境搭建与组件介绍

    Vue项目环境搭建 """ node ~~ python:node是用c++编写用来运行js代码的 npm(cnpm) ~~ pip:npm是一个终端应用商城,可以换国内 ...

  5. Vue 项目环境搭建

    Vue项目环境搭建 ''' 1) 安装node 官网下载安装包,傻瓜式安装:https://nodejs.org/zh-cn/ 2) 换源安装cnpm >: npm install -g cnp ...

  6. 在vue项目中添加一个html页面,开启本地服务器

    在vue项目里新增一个不需要登录的页面,那么我只能新增一个html页面了,不经过路由,直接在浏览器输入路径打开,那么就需要用到本地服务器, 1.vue里面的html页面最好放过在public文件夹里面 ...

  7. 【Rsync项目实战】备份全网服务器数据

    [Rsync项目实战]备份全网服务器数据 标签(空格分隔): Linux服务搭建-陈思齐 ---本教学笔记是本人学习和工作生涯中的摘记整理而成,此为初稿(尚有诸多不完善之处),为原创作品,允许转载,转 ...

  8. 【NFS项目实战二】NFS共享数据的时时同步推送备份

    [NFS项目实战二]NFS共享数据的时时同步推送备份 标签(空格分隔): Linux服务搭建-陈思齐 ---本教学笔记是本人学习和工作生涯中的摘记整理而成,此为初稿(尚有诸多不完善之处),为原创作品, ...

  9. 如何使用XAMPP本地搭建一个属于你自己的网站

    你好,从今天开始,我将为大家带来一些我学习SEO和建站的免费教程,今天为大家带来的是如何用XAMPP搭建一个属于你自己的网站.来到这里,可以说很多在百度上已经过时了的资料需要总结的资料这里都有,你只要 ...

  10. 推荐一个在线json数据格式化网站

    json数据非常友好方便的处理: 推荐一个在线json数据格式化网站 http://json.parser.online.fr/

随机推荐

  1. [737] Interlude OpCodez

    [737] Interlude Client 00 SendProtocolVersion 01 MoveBackwardToLocation 02 Say 03 RequestEnterWorld ...

  2. ubuntu16.04编译LAPACK3.7.1出错

    NEP: Testing Nonsymmetric Eigenvalue Problem routines ./EIG/xeigtstz < nep.in > znep.out 2> ...

  3. 解决Fiddler设置的代理总是被自动关闭,The system proxy was changed

    火绒剑过滤路径ProxyOverride 停用服务SangforSP https://www.cnblogs.com/jspider/p/15896503.html

  4. python 嵌套对象转为dict

    as_dict(self, keys=None, exclude_keys=None): """ 将ORM对象序列化为字典 :param keys: :return: & ...

  5. how to make the windows console works with utf-8 encoded project

    the console of the windows os is not working in the utf-8 encoding, by default. When you force your ...

  6. 2023 01 19 HW

    2023 01 19 HW Okay, then let's start.  Okay. Maybe Karina, we start with the C2 design freeze. Yeah, ...

  7. JAVA格式化数字

    DecimalFormat df = new DecimalFormat("#.##"); System.out.println(df.format(100.1234)); // ...

  8. 《Python 3.8从入门到精通(视频教学版)》PDF电子书赠阅

    <Python 3.8从入门到精通(视频教学版)>PDF电子书赠阅,个人学习使用,禁止任何形式的商用. https://pan.baidu.com/s/1U_8-N9YJVG8UsUHbQ ...

  9. httprunner运行遇到彻底解决安装包过程中的Requirement already satisfied:问题

    deMacBook-Pro:bndcs yuansanmei$ python3 -m pip install httprunner==v4.3.0Requirement already satisfi ...

  10. 【小记】copy 与 copy_backward

    copy 与 copy_backward copy 从前往后复制,result 参数指向目标容器的 begin 位置 copy*backward 从后往前复制,··· end 位置 Possible ...