文档服务地址:http://47.92.0.57:3000/ 周报索引地址:http://47.92.0.57:3000/s/NruNXRYmV

Commit 373d2fb8 by 李景熙

Merge remote-tracking branch 'origin/develop' into develop

parents 693f3927 8dc8d4e4
export function download (url, relationId) {
url = 'http://localhost:9100/api' + url + '/' + relationId
var a = document.createElement('a')
a.href = url
document.body.appendChild(a)
a.click()
document.body.removeChild(a)
}
......@@ -20,6 +20,8 @@
<span>{{item.nickname}}</span>
<el-button v-if="!item.state" type="primary" size="mini" plain @click="goto(item)">待审核</el-button>
<el-button v-else type="success" size="mini" plain @click="goto(item)">修改</el-button>
<el-button type="primary" size="mini" plain
@click="exportFile(item.relation_id)" >导出</el-button>
</li>
</ul>
</el-dialog>
......@@ -28,6 +30,7 @@
<script>
import PiecesTable from './PiecesTable'
import {download} from '@/assets/js/Download.js'
export default {
name: 'check-detail',
components: {
......@@ -88,6 +91,14 @@ export default {
case '图片': goto('imageShow'); break
case '图层': goto('layerShow')
}
},
exportFile (relationId) {
var piece = this.piece
if (piece.type === '文本') {
download('/files/downloadZip', relationId)
} else {
download('/image/export/zip', relationId)
}
}
}
}
......@@ -116,9 +127,16 @@ export default {
}
li{
list-style: none;
display: flex;
justify-content: space-between;
margin-bottom: 10px;
overflow: hidden;
span{
float: left;
line-height: 28px;
}
.el-button{
float: right;
margin-left: 10px;
}
}
}
}
......
......@@ -7,8 +7,7 @@
<div>{{item.name}}</div>
<div>发布者:{{item.creator}}&emsp;&emsp;发布时间:{{item.date|formatDate}}&emsp;&emsp;任务状态:已完成
</div>
<el-button class="task-enter-btn2" type="primary" @click="detail(item)" plain>查看任务</el-button>
<el-button class="task-enter-btn1" type="primary" plain>导出任务</el-button>
<el-button class="task-enter-btn1" type="primary" @click="detail(item)" plain>查看任务</el-button>
</div>
</div>
<navigator v-model="tasks" :condition="condition"></navigator>
......
......@@ -7,12 +7,10 @@
<el-divider></el-divider>
<pieces-table :task-id="task.id" withExecutor>
<template v-slot:option="slotProps">
<el-button
type="primary"
size="mini"
plain
@click="doOption(slotProps.file,slotProps.piece)"
>详情</el-button>
<el-button type="primary" size="mini" plain
@click="doOption(slotProps.file,slotProps.piece)">详情</el-button>
<el-button type="primary" size="mini" plain
@click="exportFile(slotProps.file,slotProps.piece)">导出</el-button>
</template>
</pieces-table>
</div>
......@@ -21,6 +19,7 @@
<script>
import PiecesTable from './PiecesTable'
import {download} from '@/assets/js/Download.js'
export default {
name: 'task',
......@@ -56,6 +55,14 @@ export default {
case '图片': goto('imageShow'); break
case '图层': goto('layerShow')
}
},
exportFile (file, piece) {
var relationId = file.relation_id
if (piece.type === '文本') {
download('/files/downloadZip', relationId)
} else {
download('/image/export/zip', relationId)
}
}
}
}
......
......@@ -15,33 +15,19 @@
@click="doOption(slotProps.file,slotProps.piece)"
>修改</el-button>
<el-button type="primary" size="mini" plain
@click="showExport(slotProps.file,slotProps.piece)"
@click="exportFile(slotProps.file,slotProps.piece)"
>导出</el-button>
</template>
</template>
</pieces-table>
</div>
<el-dialog title="选择导出类型" :visible.sync="dialogVisible" width="40%" >
<el-button v-show="dialogVisible && piece.type !== '文本'" type="primary" size="mini" plain @click="exportOriginal">原始图片</el-button>
<el-button v-show="dialogVisible && piece.type !== '文本'" type="primary" size="mini" plain @click="exportJson">JSON文件</el-button>
<el-button v-show="dialogVisible && piece.type !== '文本'" type="primary" size="mini" plain @click="exportLabel">标注后的图片</el-button>
<el-button v-show="dialogVisible && piece.type === '文本'" type="primary" size="mini" plain @click="exportText">文本文件</el-button>
<el-button v-show="dialogVisible && piece.type === '文本'" type="primary" size="mini" plain @click="exportLabelText">标注文件</el-button>
</el-dialog>
</div>
</template>
<script>
import PiecesTable from './PiecesTable'
import FileSaver from 'file-saver'
import {download} from '@/assets/js/Download.js'
function download (url) {
var a = document.createElement('a')
a.href = url
document.body.appendChild(a)
a.click()
document.body.removeChild(a)
}
export default {
name: 'on-going-task-detail',
components: {
......@@ -49,10 +35,7 @@ export default {
},
data () {
return {
task: null,
dialogVisible: false,
file: null,
piece: null
task: null
}
},
beforeMount () {
......@@ -79,47 +62,13 @@ export default {
case '图层': goto('layer')
}
},
showExport (file, piece) {
this.dialogVisible = true
this.file = file
this.piece = piece
},
exportOriginal () {
var relationId = this.file.relation_id
download(`http://localhost:9100/api/image/export/original/${relationId}`)
},
exportJson () {
var relationId = this.file.relation_id
download(`http://localhost:9100/api/image/export/json/${relationId}`)
},
exportLabel () {
var relationId = this.file.relation_id
download(`http://localhost:9100/api/image/export/label/${relationId}`)
},
// 文本组的下载参数比较复杂,放在这里更方便设置参数
async downloadText (url) {
var { file, piece } = this, self = this,
res = await this.axios.post('/textAnnotation/insertDocument', { // 拿到result_id
templateId: piece.template,
annotatorId: self.$store.state.userInfo.userId,
creatorId: self.task.creator_id,
textUrl: file.url,
type: piece.type === '文本' ? 'text' : 'xlsx',
fileId: file.id
})
res = await this.axios.post(url, { documentId: res.result })
let blob // 保存文件
if (url === '/files/downloadContent') blob = new Blob([res], {type: 'text/plain'})
else blob = new Blob([JSON.stringify(res.result)], {type: 'application/json'})
FileSaver.saveAs(blob)
},
exportText () {
this.downloadText('/files/downloadContent')
},
exportLabelText () {
this.downloadText('/textAnnotation/getTokenList')
exportFile (file, piece) {
var relationId = file.relation_id
if (piece.type === '文本') {
download('/files/downloadZip', relationId)
} else {
download('/image/export/zip', relationId)
}
}
}
}
......
......@@ -404,12 +404,13 @@
}],
dynamicValidateForm: {
//domains--文本信息
domains: [{
fileList:new Array(),
templateId:'',//模板ID
// templateName:'',
// createMode:false
}],
domains: [],
// {
// fileList:new Array(),
// templateId:'',//模板ID
// // templateName:'',
//
// }
// //domains--表格信息
// tableDomains: [{
// fileList:new Array(),
......@@ -417,14 +418,16 @@
// pname:'',
// createMode:false
// }],
pictureDomains:[{
fileList: new Array(),
description:'',
}],
layerDomains:[{
fileList: new Array(),
description:'',
}],
pictureDomains:[],
// //{
// fileList: new Array(),
// description:'',
// }
layerDomains:[],
// {
// fileList: new Array(),
// description:'',
// }
},
cardName : 'first',
createModeValue:'-1',
......@@ -461,6 +464,7 @@
}
})
if(this.ins == 2){
console.log("修改");
this.taskId = this.$route.params.taskId,
this.axios({
method:'post',
......@@ -469,8 +473,6 @@
},
url:'task/getTaskDetail'
}).then(res=>{
// console.log("ininininini");
// console.log(res);
if(res.code == 0){
alert('无法修改任务');
}
......@@ -719,6 +721,13 @@
submitForm(formName) {
// console.log("测试id");
// console.log(this.dynamicValidateForm.domains);
if(this.dynamicValidateForm.domains.length > 0 && this.pOptions.length == 0){
this.$message({
type: 'info',
message: '请创建并选择模板'
})
return
}
setTimeout(()=>{
this.axios({
method:"post",
......@@ -793,7 +802,7 @@
if(ptype == 1){
this.dynamicValidateForm.domains.push({
fileList:new Array(),
templateId:'',
templateId:1,
templateName:'',
createMode:false,
key: Date.now()
......
......@@ -131,6 +131,7 @@ export default {
templateId: this.piece.template, // TODO 模板id
annotatorId: this.$store.state.userInfo.userId,
creatorId: this.task.creator_id,
relationId: this.relationId,
textUrl: this.file.url,
type: "text",
fileId: this.file.id
......
......@@ -122,6 +122,7 @@ export default {
templateId: this.piece.template, // TODO 模板id
annotatorId: this.$store.state.userInfo.userId,
creatorId: this.task.creator_id,
relationId: this.relationId,
textUrl: this.file.url,
type: "text",
fileId: this.file.id
......
......@@ -107,6 +107,7 @@ export default {
templateId: this.piece.template, // TODO 模板id
annotatorId: this.$store.state.userInfo.userId,
creatorId: this.task.creator_id,
relationId: this.relationId,
textUrl: this.file.url,
type: "text",
fileId: this.file.id
......
......@@ -178,6 +178,7 @@ export default {
templateId: this.piece.template, // TODO 模板id
annotatorId: this.$store.state.userInfo.userId,
creatorId: this.task.creator_id,
relationId: this.relationId,
textUrl: this.file.url,
type: "xlsx",
fileId: this.file.id
......
......@@ -166,6 +166,7 @@ export default {
templateId: this.piece.template, // TODO 模板id
annotatorId: this.$store.state.userInfo.userId,
creatorId: this.task.creator_id,
relationId: this.relationId,
textUrl: this.file.url,
type: "xlsx",
fileId: this.file.id
......
......@@ -178,6 +178,7 @@ export default {
templateId: this.piece.template, // TODO 模板id
annotatorId: this.$store.state.userInfo.userId,
creatorId: this.task.creator_id,
relationId: this.relationId,
textUrl: this.file.url,
type: "xlsx",
fileId: this.file.id
......
......@@ -6,7 +6,6 @@ import io
import PIL.Image
import PIL.ImageDraw
from flask import make_response
from flask_mongoengine import MongoEngine
import views.uploadDownload as fileDownload
......@@ -158,18 +157,38 @@ def get_img_point_lists(relation_id):
return point_lists
# 根据relationId获取原始图片的属性
def get_img_type(relation_id):
image_name = get_img_name(relation_id)
img_dict = {
'jpeg': 'image/jpeg',
'jpg': 'image/jpeg',
'png': 'image/png',
'gif': 'image/gif'
}
img_type = image_name.split('.')[-1].lower()
mine = img_dict[img_type]
return img_type, mine
# 根据relationId获取原始图片对象
def export_original_img(relation_id):
def export_original_img_bytes(relation_id):
try:
image_name = get_img_name(relation_id)
return fileDownload.download(image_name)
img_dir = fileDownload.get_image_dir(image_name)
with open(img_dir, 'rb') as f:
a = f.read()
return io.BytesIO(a)
except Exception as e:
traceback.print_exc()
return Result(0, repr(e), {})
# 根据relationId获取图片json对象
def export_img_json(relation_id):
def export_img_json_bytes(relation_id):
try:
ret = {'version': '3.10.0', 'flags': {}}
obj = Image.objects(relationId=relation_id).first()
......@@ -208,18 +227,18 @@ def export_img_json(relation_id):
ret['imageHeight'] = img_size[1]
ret['imageWidth'] = img_size[0]
json_io = io.BytesIO()
img_json = json.dumps(ret, ensure_ascii=False, indent=4)
response = make_response(img_json)
response.headers["Content-Disposition"] = "p_w_upload; filename={}.json".format(image_name.split('.')[0])
json_io.write(img_json.encode())
return img_json, json_io
return response
except Exception as e:
traceback.print_exc()
return Result(0, repr(e), {})
# 根据relationId获取标注图片对象
def export_label_img(relation_id):
def export_label_img_bytes(relation_id):
try:
# 生成图片
image_name = get_img_name(relation_id)
......@@ -238,18 +257,9 @@ def export_label_img(relation_id):
draw.polygon(p, fill=c)
# 发送图片
img_dict = {
'jpeg': 'image/jpeg',
'jpg': 'image/jpeg',
'png': 'image/png',
'gif': 'image/gif'
}
img_type = image_name.split('.')[-1].lower()
# 这里只测试了 jpg 图像(数据库中只有这个,可能发布的人比较喜欢这个格式吧。。)
# 可能存在问题,等待后续测试
mine = img_dict[img_type]
_, mine = get_img_type(relation_id)
if mine == 'image/jpeg':
img = img.convert('RGB')
......@@ -257,12 +267,7 @@ def export_label_img(relation_id):
img.save(img_io, mine.split('/')[-1], quality=70)
img_io.seek(0)
response = make_response(img_io.getvalue())
img_io.close()
response.headers["Content-Type"] = mine
response.headers["Content-Disposition"] = "attachment; filename={}_label.{}".format(image_name.split('.')[0],
img_type)
return response
return img_io
except Exception as e:
traceback.print_exc()
......
[{'word': '具体信息', 'begin': 19, 'end': 23, 'entityId': '', 'attribute': [], 'tokenId': 'bdff507ed0c511eab562fa2819d635b1'}]
\ No newline at end of file
[{'word': 'urn ', 'begin': 286, 'end': 290, 'entityId': '', 'attribute': [], 'tokenId': 'dcc13392d0e011eab507e442a67d6c47'}]
\ No newline at end of file
参加过一次软院心理讲座,但是未录入
有博雅记录的一共4次
总共5次博雅
\ No newline at end of file
参加过一次软院心理讲座,但是未录入
有博雅记录的一共4次
总共5次博雅
\ No newline at end of file
参加过一次软院心理讲座,但是未录入
有博雅记录的一共4次
总共5次博雅
\ No newline at end of file
参加过一次软院心理讲座,但是未录入
有博雅记录的一共4次
总共5次博雅
\ No newline at end of file
import json
from flask import Blueprint, request, Response
import io
import traceback
import zipfile
from flask import Blueprint, request, make_response, send_file
from dao import Image, Relation
image = Blueprint("image", __name__, url_prefix="/api")
def handle_except(result):
res = {
'code': result.code,
'message': result.message,
'data': result.data
}
return json.dumps(res, ensure_ascii=False)
# 获取图片
@image.route("/image/getImage", methods=["POST"])
def get_image():
......@@ -13,12 +25,7 @@ def get_image():
relation_list = data['relationList']
# relation_list = request.args['relationList']
image = Image.getImage(relation_list)
res = {
'code': image.code,
'message': image.message,
'data': image.data
}
return json.dumps(res, ensure_ascii=False)
return handle_except(image)
# 保存图片标注结果
......@@ -48,12 +55,7 @@ def get_layer():
data = json.loads(request.data)
relation_list = data['relationId']
layer = Image.getLayer(relation_list)
res = {
'code': layer.code,
'message': layer.message,
'data': layer.data
}
return json.dumps(res, ensure_ascii=False)
return handle_except(layer)
# 保存图层标注结果
......@@ -83,49 +85,102 @@ def save_layer():
# 导出原始图片
@image.route("/image/export/original/<relationId>", methods=['GET'])
def export_original_img(relationId):
# 原始图像
original_img = Image.export_original_img(relationId)
if not isinstance(original_img, Response):
res = {
'code': original_img.code,
'message': original_img.message,
'data': original_img.data
}
return json.dumps(res, ensure_ascii=False)
try:
image_name = Image.get_img_name(relationId)
img_type, mine = Image.get_img_type(relationId)
# 原始图像
original_img_bytes = Image.export_original_img_bytes(relationId)
if not isinstance(original_img_bytes, io.BytesIO):
return handle_except(original_img_bytes)
response = make_response(original_img_bytes.getvalue())
original_img_bytes.close()
response.headers["Content-Type"] = mine
response.headers["Content-Disposition"] = "attachment; filename={}".format(image_name)
return response
return original_img
except Exception as e:
traceback.print_exc()
return handle_except(Image.Result(0, repr(e), {}))
# 导出标注图片的 json
@image.route("/image/export/json/<relationId>", methods=['GET'])
def export_json(relationId):
# json
img_json = Image.export_img_json(relationId)
if isinstance(img_json, Image.Result):
res = {
'code': img_json.code,
'message': img_json.message,
'data': img_json.data
}
return json.dumps(res, ensure_ascii=False)
try:
image_name = Image.get_img_name(relationId)
# json
img_json_bytes, _ = Image.export_img_json_bytes(relationId)
if isinstance(img_json_bytes, Image.Result):
return handle_except(img_json_bytes)
response = make_response(img_json_bytes)
response.headers["Content-Disposition"] = "p_w_upload; filename={}.json".format(image_name.split('.')[0])
return response
return img_json
except Exception as e:
traceback.print_exc()
return handle_except(Image.Result(0, repr(e), {}))
# 导出标注后的图片
@image.route("/image/export/label/<relationId>", methods=['GET'])
def export_label(relationId):
# 标注图像
label_img = Image.export_label_img(relationId)
if isinstance(label_img, Image.Result):
res = {
'code': label_img.code,
'message': label_img.message,
'data': label_img.data
}
return json.dumps(res, ensure_ascii=False)
return label_img
try:
# 标注图像
label_img_bytes = Image.export_label_img_bytes(relationId)
image_name = Image.get_img_name(relationId)
img_type, mine = Image.get_img_type(relationId)
if isinstance(label_img_bytes, Image.Result):
return handle_except(label_img_bytes)
response = make_response(label_img_bytes.getvalue())
label_img_bytes.close()
response.headers["Content-Type"] = mine
response.headers["Content-Disposition"] = "attachment; filename={}_label.{}".format(image_name.split('.')[0],
img_type)
return response
except Exception as e:
traceback.print_exc()
return handle_except(Image.Result(0, repr(e), {}))
# 导出压缩文件
@image.route("/image/export/zip/<relationId>", methods=['GET'])
def export_zip(relationId):
try:
image_name = Image.get_img_name(relationId)
img_type = image_name.split('.')[-1].lower()
image_name = image_name.split('.')[0]
# 3 files' Bytes
original_img_bytes = Image.export_original_img_bytes(relationId)
label_img_bytes = Image.export_label_img_bytes(relationId)
_, json_img_bytes = Image.export_img_json_bytes(relationId)
bytes = [original_img_bytes, json_img_bytes, label_img_bytes]
types = [image_name + '.' + img_type, image_name + '.json', image_name + '_label.' + img_type]
# zip file
zip_buffer = io.BytesIO()
with zipfile.ZipFile(zip_buffer, "a", zipfile.ZIP_DEFLATED, False) as zip_file:
for file_name, data in zip(types, bytes):
zip_file.writestr(file_name, data.getvalue())
data.close()
zip_buffer.seek(0)
return send_file(zip_buffer, attachment_filename=image_name + '.zip', as_attachment=True)
except Exception as e:
traceback.print_exc()
return handle_except(Image.Result(0, repr(e), {}))
# 保存图片标注结果的测试数据
# {
......
......@@ -181,17 +181,18 @@ def insertDocument():
templateId = get_Data.get('templateId', None)
creatorId = get_Data.get('creatorId', None)
annotatorId = get_Data.get('annotatorId', None)
relationId = get_Data.get('relationId', None)
fileId = get_Data.get('fileId', None)
textUrl = get_Data.get('textUrl', None)
type = get_Data.get('type', None)
if templateId is None or creatorId is None or annotatorId is None or fileId is None or textUrl is None or type is None:
if templateId is None or creatorId is None or annotatorId is None or relationId is None or fileId is None or textUrl is None or type is None:
return_dict['return_code'] = '201'
return_dict['return_info'] = '请求参数有误'
return json.dumps(return_dict, ensure_ascii=False)
result = mongodbApi.findOne(collectionTest, {"templateId": templateId, "creatorId": creatorId, "annotatorId": annotatorId, "fileId": fileId,
"textUrl": textUrl, "type": type})
result = mongodbApi.findOne(collectionTest, {"templateId": templateId, "creatorId": creatorId, "annotatorId": annotatorId,
"relationId": relationId, "fileId": fileId, "textUrl": textUrl, "type": type})
if result is not None:
return_dict['result'] = result.get("documentId", None)
......@@ -200,7 +201,7 @@ def insertDocument():
documentId = str(uuid.uuid1()).replace('-', '')
result = mongodbApi.insert(collectionTest, {"documentId": documentId, "templateId": templateId, "creatorId": creatorId,
"annotatorId": annotatorId, "fileId": fileId, "textUrl": textUrl, "state": "0",
"annotatorId": annotatorId, "relationId": relationId, "fileId": fileId, "textUrl": textUrl, "state": "0",
"type": type, "tokenList": []})
if result is None:
......
......@@ -7,9 +7,11 @@ import PIL.Image
from datetime import datetime
import xlrd
import zipfile
from flask import Blueprint
from xlrd import xldate_as_tuple
from werkzeug.utils import secure_filename
from dao import mongodbApi
from support import basedir
......@@ -19,6 +21,7 @@ from views.textAnnotation import collectionTest
uploadDownload = Blueprint("uploadDownload", __name__, url_prefix="/api/files")
UPLOAD_FOLDER = 'upload' # 用于保存上传文件的文件夹名称
ZIP_FOLDER = 'zip' # 用于保存zip文件的文件夹名称
ALLOWED_EXTENSIONS = {'txt', 'xls', 'xlsx', 'png', 'jpg', 'bmp', 'gif'} # 允许上传的文件格式
......@@ -128,6 +131,14 @@ def get_image_file(imageName):
return jsonify({"code": 0, "errmsg": repr(e)})
# 根据图片名称返回图片所在路径
def get_image_dir(imageName):
file_dir = os.path.join(basedir, UPLOAD_FOLDER, imageName)
if not os.path.exists(file_dir):
return None
return file_dir
# 根据图片名称返回图片的 base64 编码
def get_image_base64(imageName):
try:
......@@ -268,3 +279,53 @@ def downloadContent():
file_dir = os.path.join(basedir, UPLOAD_FOLDER, url)
return send_file(file_dir, as_attachment=True, attachment_filename=url)
# 打包下载
@uploadDownload.route('/downloadFile', methods=['POST'])
def downloadFile():
get_Data = request.get_data()
get_Data = json.loads(get_Data)
relationId = get_Data.get('relationId')
result = mongodbApi.findOne(collectionTest, {"relationId": relationId})
url = result.get('textUrl')
file_dir = os.path.join(basedir, UPLOAD_FOLDER, url)
return send_file(file_dir, as_attachment=True, attachment_filename=url)
# 下载压缩包接口
@uploadDownload.route('/downloadZip/<relationId>', methods=['GET'])
def downloadZip(relationId):
relationId = int(relationId)
result = mongodbApi.findOne(collectionTest, {"relationId": relationId})
url = result.get('textUrl')
file_dir = os.path.join(basedir, UPLOAD_FOLDER) # 被压缩的文件所在文件夹路径 如 D:\learn\python-project\demo\upload
zip_dir = os.path.join(basedir, ZIP_FOLDER) # 压缩后的文件所在文件夹路径 如 D:\learn\python-project\demo\zip
portion = os.path.splitext(url) # 获取文件前缀名 如1590310217.txt portion[0]则为1590310217
new_name = portion[0] + '.zip' # 新的文件名字 如1590310217.zip
zipname = os.path.join(zip_dir,
new_name) # 压缩的文件夹名字及路径 如 D:\learn\python-project\demo\zip\1590310217.zip (这是我电脑上的路径)
f = zipfile.ZipFile(zipname, 'w', zipfile.ZIP_DEFLATED) # 创建压缩文件 'w':写模式 ZIP_DEFLATED:设置压缩格式
basename = url # 压缩后文件的根目录叫啥
fpath = os.path.join(file_dir, url) # fpath就是被压缩的文件的路径的集合 file_dir代表被压缩的文件的路径 name是被压缩的文件的名字
arcname = os.path.join(basename, url) # 这个不用管 是为了让压缩后的文件的根目录只有一层 不然会套娃n个文件夹(一层路径一个文件夹)
f.write(fpath, arcname=arcname) # 写进去 压缩!
json_name = portion[0] + 'result.json' # 新的文件名字 如1590310217result.txt
full_path = os.path.join(file_dir, json_name) # 标注结果文件保存位置 + 标注结果文件名
file = open(full_path, 'w', encoding='utf8') # 打开文件
file.write(str(result.get('tokenList'))) # 写入标注结果字符串
file.close() # 关闭文件
fpath = os.path.join(file_dir, json_name) # fpath就是被压缩的文件的路径的集合 file_dir代表被压缩的文件的路径 name是被压缩的文件的名字
arcname = os.path.join(basename, json_name) # 这个不用管 是为了让压缩后的文件的根目录只有一层 不然会套娃n个文件夹(一层路径一个文件夹)
f.write(fpath, arcname=arcname) # 写进去 压缩!
f.close() # 关闭
return send_file(zipname, as_attachment=True, attachment_filename=new_name)
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment