app.py 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338
  1. import os
  2. import sys
  3. import uuid
  4. import tempfile
  5. import pdfplumber
  6. from flask import Flask, request, jsonify, send_file
  7. from add_signature import find_signature_positions, add_signature_to_pdf
  8. from add_watermark import add_watermark_to_pdf
  9. from extract_table import extract_temp_time, extract_pdf_table_to_excel, extract_temp_by_datetime_pattern, allowed_file, \
  10. safe_filename, extract_temperature_data_from_pdf, extract_data_from_pdf_5
  11. from drag_signature import add_signature_at_position, add_multiple_signatures
  12. from lib import Qiniu
  13. from werkzeug.utils import secure_filename
  14. from flask_cors import CORS
  15. app = Flask(__name__)
  16. UPLOAD_FOLDER = tempfile.gettempdir()
  17. app.config['UPLOAD_FOLDER'] = UPLOAD_FOLDER
  18. CORS(app)
  19. # 确保temp目录存在
  20. temp_dir = "./temp"
  21. if not os.path.exists(temp_dir):
  22. os.makedirs(temp_dir)
  23. @app.route('/add_signature', methods=['POST'])
  24. def add_signature():
  25. try:
  26. # 获取请求参数
  27. data = request.get_json()
  28. pdf_url = data.get('pdf_url')
  29. if not pdf_url:
  30. return jsonify({"error": "缺少pdf_url参数"}), 400
  31. # 下载PDF文件
  32. local_pdf = Qiniu.download_file(pdf_url)
  33. # 查找签名位置(使用默认公章图片)
  34. signature_img = './static/报告专用章.png' # 确保项目目录下有这个文件
  35. positions = find_signature_positions(local_pdf)
  36. if not positions:
  37. os.remove(local_pdf)
  38. return jsonify({"error": "未找到签名位置"}), 400
  39. # 生成带公章的PDF
  40. signature_pdf = os.path.join("./temp", f"signature_{os.path.basename(local_pdf)}")
  41. add_signature_to_pdf(local_pdf, signature_pdf, signature_img, positions)
  42. # 上传到七牛云
  43. file_key = f"UpImage/{uuid.uuid4()}.pdf"
  44. new_pdf_url = Qiniu.upload_to_qiniu(signature_pdf, file_key)
  45. # 清理临时文件
  46. os.remove(local_pdf)
  47. os.remove(signature_pdf)
  48. return jsonify({
  49. "success": True,
  50. "signature_pdf_url": new_pdf_url
  51. })
  52. except Exception as e:
  53. return jsonify({
  54. "error": str(e),
  55. "success": False,
  56. }), 500
  57. @app.route('/add_watermark', methods=['POST'])
  58. def add_watermark():
  59. try:
  60. # 获取请求参数
  61. data = request.get_json()
  62. pdf_url = data.get('pdf_url')
  63. if not pdf_url:
  64. return jsonify({"error": "缺少pdf_url参数"}), 400
  65. # 下载PDF文件
  66. local_pdf = Qiniu.download_file(pdf_url)
  67. # 水印文件
  68. pdf_file_mark = './static/watermark.pdf' # 确保项目目录下有这个文件
  69. # 生成带公章的PDF
  70. watermark_pdf = os.path.join("./temp", f"watermark_{os.path.basename(local_pdf)}")
  71. add_watermark_to_pdf(local_pdf, pdf_file_mark, watermark_pdf)
  72. # 上传到七牛云
  73. file_key = f"UpImage/{uuid.uuid4()}.pdf"
  74. new_pdf_url = Qiniu.upload_to_qiniu(watermark_pdf, file_key)
  75. # 清理临时文件
  76. os.remove(local_pdf)
  77. os.remove(watermark_pdf)
  78. return jsonify({
  79. "success": True,
  80. "watermark_pdf_url": new_pdf_url
  81. })
  82. except Exception as e:
  83. return jsonify({
  84. "error": str(e),
  85. "success": False,
  86. }), 500
  87. @app.route('/extract_table', methods=['POST'])
  88. def extract_table():
  89. if 'file' not in request.files:
  90. return jsonify({'error': 'No file part'}), 400
  91. file = request.files['file']
  92. if file.filename == '':
  93. return jsonify({'error': 'No selected file'}), 400
  94. if file and allowed_file(file.filename):
  95. original_filename = file.filename
  96. filename = safe_filename(original_filename)
  97. # filename = secure_filename(safe_name)
  98. filepath = os.path.join(app.config['UPLOAD_FOLDER'], filename)
  99. file.save(filepath)
  100. df = None
  101. with pdfplumber.open(filepath) as pdf:
  102. # 获取第一页
  103. first_page = pdf.pages[0]
  104. text = first_page.extract_text()
  105. if text:
  106. if "温湿度数据报告" in text:
  107. df = extract_pdf_table_to_excel(filepath)
  108. if "历史数据表" in text:
  109. df = extract_temp_time(filepath)
  110. if "设备汇总报告" in text:
  111. df = extract_temp_by_datetime_pattern(filepath)
  112. if "详细数据" in text:
  113. df = extract_temperature_data_from_pdf(filepath)
  114. else:
  115. df = extract_data_from_pdf_5(filepath)
  116. if df is None:
  117. os.remove(filepath)
  118. return jsonify({'error': '所有处理方法均失败'}), 400
  119. # 保存Excel文件
  120. output_filename = filename.replace('.pdf', '.xlsx')
  121. output_path = os.path.join(app.config['UPLOAD_FOLDER'], output_filename)
  122. df.to_excel(output_path, index=False, engine='openpyxl')
  123. # 删除上传的PDF文件
  124. os.remove(filepath)
  125. # 返回Excel文件
  126. try:
  127. return send_file(
  128. output_path,
  129. as_attachment=True,
  130. download_name=output_filename,
  131. mimetype='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'
  132. )
  133. finally:
  134. # 确保临时文件最终被删除
  135. try:
  136. os.remove(output_path)
  137. except:
  138. pass
  139. else:
  140. return jsonify({'error': 'Invalid file type'}), 400
  141. @app.route('/upload_pdf', methods=['POST'])
  142. def upload_pdf():
  143. """
  144. 上传PDF文件到服务器并返回URL
  145. """
  146. try:
  147. if 'file' not in request.files:
  148. return jsonify({"error": "没有文件"}), 400
  149. file = request.files['file']
  150. if file.filename == '':
  151. return jsonify({"error": "文件名为空"}), 400
  152. if not file.filename.lower().endswith('.pdf'):
  153. return jsonify({"error": "只支持PDF文件"}), 400
  154. # 保存临时文件
  155. filename = secure_filename(file.filename)
  156. temp_pdf = os.path.join("./temp", f"upload_{uuid.uuid4()}.pdf")
  157. file.save(temp_pdf)
  158. # 上传到七牛云
  159. file_key = f"UpImage/{uuid.uuid4()}.pdf"
  160. pdf_url = Qiniu.upload_to_qiniu(temp_pdf, file_key)
  161. # 清理临时文件
  162. try:
  163. os.remove(temp_pdf)
  164. except:
  165. pass
  166. return jsonify({
  167. "success": True,
  168. "pdf_url": pdf_url
  169. })
  170. except Exception as e:
  171. return jsonify({
  172. "error": str(e),
  173. "success": False,
  174. }), 500
  175. @app.route('/upload_signature', methods=['POST'])
  176. def upload_signature():
  177. """
  178. 上传签名图片文件到服务器并返回URL
  179. """
  180. try:
  181. if 'file' not in request.files:
  182. return jsonify({"error": "没有文件"}), 400
  183. file = request.files['file']
  184. if file.filename == '':
  185. return jsonify({"error": "文件名为空"}), 400
  186. # 检查文件类型(支持常见的图片格式)
  187. allowed_extensions = {'.png', '.jpg', '.jpeg', '.gif', '.bmp', '.webp'}
  188. filename_lower = file.filename.lower()
  189. if not any(filename_lower.endswith(ext) for ext in allowed_extensions):
  190. return jsonify({"error": "只支持图片文件(png, jpg, jpeg, gif, bmp, webp)"}), 400
  191. # 保存临时文件
  192. filename = secure_filename(file.filename)
  193. # 获取文件扩展名
  194. file_ext = os.path.splitext(filename)[1] or '.png'
  195. temp_signature = os.path.join("./temp", f"upload_signature_{uuid.uuid4()}{file_ext}")
  196. file.save(temp_signature)
  197. # 上传到七牛云
  198. file_key = f"UpImage/{uuid.uuid4()}{file_ext}"
  199. signature_url = Qiniu.upload_to_qiniu(temp_signature, file_key)
  200. # 清理临时文件
  201. try:
  202. os.remove(temp_signature)
  203. except:
  204. pass
  205. return jsonify({
  206. "success": True,
  207. "signature_url": signature_url
  208. })
  209. except Exception as e:
  210. return jsonify({
  211. "error": str(e),
  212. "success": False,
  213. }), 500
  214. @app.route('/drag_signature', methods=['POST'])
  215. def drag_signature():
  216. """
  217. 在PDF上添加签名或电子章(支持拖放)
  218. 请求参数:
  219. {
  220. "pdf_url": "PDF文件URL",
  221. "signatures": [
  222. {
  223. "signature_url": "签名/电子章URL",
  224. "page_num": 页码(从0开始),
  225. "x": X坐标(相对于页面左上角,单位:点),
  226. "y": Y坐标(相对于页面左上角,单位:点),
  227. "width": 宽度(可选,单位:点),
  228. "height": 高度(可选,单位:点)
  229. }
  230. ]
  231. }
  232. """
  233. try:
  234. # 获取请求参数
  235. data = request.get_json()
  236. pdf_url = data.get('pdf_url')
  237. signatures = data.get('signatures', [])
  238. if not pdf_url:
  239. return jsonify({"error": "缺少pdf_url参数"}), 400
  240. if not signatures or len(signatures) == 0:
  241. return jsonify({"error": "缺少signatures参数或签名列表为空"}), 400
  242. # 下载PDF文件
  243. local_pdf = Qiniu.download_file(pdf_url)
  244. # 生成带签名的PDF
  245. output_pdf = os.path.join("./temp", f"drag_signature_{uuid.uuid4()}.pdf")
  246. # 添加多个签名
  247. add_multiple_signatures(local_pdf, output_pdf, signatures)
  248. # 上传到七牛云
  249. file_key = f"UpImage/{uuid.uuid4()}.pdf"
  250. new_pdf_url = Qiniu.upload_to_qiniu(output_pdf, file_key)
  251. # 清理临时文件
  252. try:
  253. os.remove(local_pdf)
  254. os.remove(output_pdf)
  255. except:
  256. pass
  257. return jsonify({
  258. "success": True,
  259. "pdf_url": new_pdf_url
  260. })
  261. except Exception as e:
  262. return jsonify({
  263. "error": str(e),
  264. "success": False,
  265. }), 500
  266. if __name__ == '__main__':
  267. print("项目地址:", os.path.dirname(__file__))
  268. if len(sys.argv) != 2:
  269. print("请填写端口号")
  270. sys.exit()
  271. # app.debug = True # 设置调试模式,生产模式的时候要关掉debug
  272. # app.config['JSON_AS_ASCII'] = False
  273. app.run(host='0.0.0.0', port=6500, debug=True)