业务背景
- 近期用Python-Flask开发项目遇到一个多文件打包下载的业务接口,文件格式有Excel、图片文件、视频文件打包成zip下载。
- 前端通过接口发送ID,后端通过ID查询数据库相关数据并生成Excel文档、数据库查出图片和视频地址之后下载到服务器、打包成压缩包返回给前端。
实现思路
- 后端根据ID创建文件夹到服务器目录
- 查找数据库数据生成Excel文件,并存储到第一步生成的文件夹内
- 根据数据库查找到的文件(图片、视频)URL地址下载文件,并存储到第一步生成的文件夹内
- 将文件夹打包zip
- 返回给前端
项目代码
- 项目基于Flask
- 篇幅原因只贴出本下载接口业务相关代码
api.add_resource(Download, "/activities/download/<int:activities_id>")
from extensions import db
import datetime
class Activities(db.Model):
"""
活动
"""
__tablename__ = 'activities'
id = db.Column(db.Integer, primary_key=True)
active = db.Column(db.String(64))
active_type = db.Column(db.String(64))
active_time = db.Column(db.Integer)
active_object = db.Column(db.String(164))
description = db.Column(db.String(164))
image = db.Column(db.String(1024))
video = db.Column(db.String(1024))
idea_name = db.Column(db.String(164))
learn_name = db.Column(db.String(164))
learn_id = db.Column(db.String(164))
create_time = db.Column(db.DateTime, default=datetime.datetime.now)
update_time = db.Column(db.DateTime, default=datetime.datetime.now, onupdate=datetime.datetime.now)
is_delete = db.Column(db.Integer, default=0)
status = db.Column(db.Integer, default=0)
from flask import make_response, send_from_directory
import os, zipfile, re, xlsxwriter, requests
from models import Activities
class Download(Resource):
def get(self, activities_id):
path=os.path.abspath(os.path.dirname(os.path.dirname(__file__)))+"/static/"
fileDownloadPath = path.replace('\\', '/')
filePath = fileDownloadPath+ str(activities_id)+"/"
if os.path.exists(filePath):
shutil.rmtree(filePath)
os.makedirs(filePath)
object = Activities.query.filter(and_(Activities.id == activities_id, Activities.is_delete != 1)).first()
create_workbook(object, filePath+"Active.xlsx")
if object.image is not None:
imageUrl = re.findall('http[s]?://(?:[a-zA-Z]|[0-9]|[$-_@.&+]|[!*\(\),]|(?:%[0-9a-fA-F][0-9a-fA-F]))+', str(object.image))
if imageUrl is not None:
for data in imageUrl:
getFile(filePath, data, "Image"+str(imageUrl.index(data)))
if object.video is not None:
videoUrl = re.findall('http[s]?://(?:[a-zA-Z]|[0-9]|[$-_@.&+]|[!*\(\),]|(?:%[0-9a-fA-F][0-9a-fA-F]))+', str(object.video))
if videoUrl is not None:
for data in videoUrl:
getFile(filePath, data, "Video" + str(videoUrl.index(data)))
make_zip(filePath, fileDownloadPath+str(activities_id)+".zip")
response = make_response(
send_from_directory(fileDownloadPath, str(activities_id)+".zip", as_attachment=True))
return response
def create_workbook(object, filePath):
workbook = xlsxwriter.Workbook(filePath)
worksheet = workbook.add_worksheet("sheet")
title = ["Activity Types", "Activity Details", "Duration Hours", "With Whom", "Description", "Learnings", "Ideas"]
worksheet.write_row('A1', title)
worksheet.write_row('A2', [str(object.active),
str(object.active_type),
str(object.active_time),
str(object.active_object),
str(object.description),
str(object.learn_name),
str(object.idea_name)
])
workbook.close()
def getFile(filePath, url, fileName):
response = requests.get(url).content
with open(filePath+fileName+url[-4:], 'wb') as f:
f.write(response)
print ("Sucessful to download "+fileName)
def make_zip(filePath, source_dir):
zipf = zipfile.ZipFile(source_dir, 'w')
pre_len = len(os.path.dirname(filePath))
for parent, dirnames, filenames in os.walk(filePath):
for filename in filenames:
pathfile = os.path.join(parent, filename)
arcname = pathfile[pre_len:].strip(os.path.sep)
zipf.write(pathfile, arcname)
zipf.close()