mac9087 commited on
Commit
97de2ec
·
verified ·
1 Parent(s): c0d4496

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +113 -39
app.py CHANGED
@@ -1,19 +1,33 @@
1
- from flask import Flask, request, send_file, jsonify
2
  from flask_cors import CORS
3
  import fitz # PyMuPDF
4
  import os
5
  import tempfile
 
6
 
7
  app = Flask(__name__)
8
- CORS(app) # Allow all origins by default (or restrict via origins=["http://localhost:3000"])
9
 
10
- def compress_pdf(input_path, output_path):
11
  """
12
  Compresses a PDF using PyMuPDF with deflate and garbage collection.
 
13
  """
14
- doc = fitz.open(input_path)
15
- doc.save(output_path, garbage=4, deflate=True, clean=True)
16
- doc.close()
 
 
 
 
 
 
 
 
 
 
 
 
17
 
18
  @app.route("/")
19
  def home():
@@ -21,39 +35,99 @@ def home():
21
 
22
  @app.route("/compress", methods=["POST"])
23
  def compress():
24
- if 'pdf' not in request.files:
25
- return jsonify({"error": "No PDF file uploaded."}), 400
26
-
27
- target_size_str = request.form.get("target_size")
28
- if not target_size_str:
29
- return jsonify({"error": "Target size not specified."}), 400
30
-
31
  try:
32
- if target_size_str.lower().endswith("mb"):
33
- target_kb = float(target_size_str[:-2]) * 1024
34
- elif target_size_str.lower().endswith("kb"):
35
- target_kb = float(target_size_str[:-2])
36
- else:
37
- target_kb = float(target_size_str)
38
- except ValueError:
39
- return jsonify({"error": "Invalid target size format."}), 400
40
-
41
- pdf_file = request.files['pdf']
42
-
43
- with tempfile.NamedTemporaryFile(delete=False, suffix=".pdf") as input_temp:
44
- pdf_file.save(input_temp.name)
45
- input_path = input_temp.name
46
-
47
- output_path = input_path.replace(".pdf", "_compressed.pdf")
48
- compress_pdf(input_path, output_path)
49
-
50
- final_size_kb = os.path.getsize(output_path) / 1024
51
-
52
- if final_size_kb > target_kb + 50:
53
- os.remove(output_path)
54
- return jsonify({"error": f"Unable to compress below {target_kb} KB. Compressed size was {int(final_size_kb)} KB."}), 500
55
-
56
- return send_file(output_path, as_attachment=True, download_name="compressed.pdf")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
57
 
58
  if __name__ == "__main__":
59
- app.run(host="0.0.0.0", port=7860)
 
1
+ from flask import Flask, request, send_file, jsonify
2
  from flask_cors import CORS
3
  import fitz # PyMuPDF
4
  import os
5
  import tempfile
6
+ import shutil
7
 
8
  app = Flask(__name__)
9
+ CORS(app) # This will allow all origins
10
 
11
+ def compress_pdf(input_path, output_path, compression_level=4):
12
  """
13
  Compresses a PDF using PyMuPDF with deflate and garbage collection.
14
+ Allows adjusting the compression level (1-4, higher = more compression)
15
  """
16
+ try:
17
+ doc = fitz.open(input_path)
18
+ doc.save(
19
+ output_path,
20
+ garbage=compression_level, # 4 is max compression
21
+ deflate=True,
22
+ clean=True,
23
+ pretty=False, # Disable pretty printing for smaller size
24
+ linear=True # Create a linearized PDF
25
+ )
26
+ doc.close()
27
+ return True
28
+ except Exception as e:
29
+ print(f"Error compressing PDF: {str(e)}")
30
+ return False
31
 
32
  @app.route("/")
33
  def home():
 
35
 
36
  @app.route("/compress", methods=["POST"])
37
  def compress():
38
+ # Track temporary directories to clean up
39
+ temp_dirs = []
40
+
 
 
 
 
41
  try:
42
+ if 'pdf' not in request.files:
43
+ return jsonify({"error": "No PDF file uploaded."}), 400
44
+
45
+ target_size_str = request.form.get("target_size")
46
+ if not target_size_str:
47
+ return jsonify({"error": "Target size not specified."}), 400
48
+
49
+ # Parse target size
50
+ try:
51
+ if target_size_str.lower().endswith("mb"):
52
+ target_kb = float(target_size_str[:-2]) * 1024
53
+ elif target_size_str.lower().endswith("kb"):
54
+ target_kb = float(target_size_str[:-2])
55
+ else:
56
+ target_kb = float(target_size_str)
57
+ except ValueError:
58
+ return jsonify({"error": "Invalid target size format."}), 400
59
+
60
+ # Create a temporary directory
61
+ temp_dir = tempfile.mkdtemp()
62
+ temp_dirs.append(temp_dir)
63
+
64
+ # Process PDF
65
+ pdf_file = request.files['pdf']
66
+ input_path = os.path.join(temp_dir, "input.pdf")
67
+ output_path = os.path.join(temp_dir, "compressed.pdf")
68
+
69
+ pdf_file.save(input_path)
70
+ original_size_kb = os.path.getsize(input_path) / 1024
71
+
72
+ print(f"Original size: {original_size_kb:.2f} KB, Target: {target_kb:.2f} KB")
73
+
74
+ # Try different compression levels if needed
75
+ for compression_level in [4, 3, 2, 1]:
76
+ # If original file is already below target, just use it
77
+ if original_size_kb <= target_kb:
78
+ shutil.copy(input_path, output_path)
79
+ break
80
+
81
+ compress_pdf(input_path, output_path, compression_level)
82
+ final_size_kb = os.path.getsize(output_path) / 1024
83
+
84
+ print(f"Compression level {compression_level} result: {final_size_kb:.2f} KB")
85
+
86
+ # If we reached target or can't compress anymore, stop
87
+ if final_size_kb <= target_kb or compression_level == 1:
88
+ break
89
+
90
+ # Get final compressed size
91
+ final_size_kb = os.path.getsize(output_path) / 1024
92
+
93
+ # If final size is too large, inform but still provide the file
94
+ if final_size_kb > target_kb:
95
+ return jsonify({
96
+ "warning": f"Unable to compress below {target_kb:.2f} KB. Best compressed size is {int(final_size_kb)} KB.",
97
+ "original_size_kb": round(original_size_kb, 2),
98
+ "compressed_size_kb": round(final_size_kb, 2),
99
+ "target_size_kb": round(target_kb, 2),
100
+ "compression_ratio": round((original_size_kb - final_size_kb) / original_size_kb * 100, 2),
101
+ "download_available": True
102
+ }), 200
103
+
104
+ # Return the compressed file
105
+ response = send_file(output_path, as_attachment=True, download_name="compressed.pdf")
106
+
107
+ # Add cleanup function to be called after response is sent
108
+ @response.call_on_close
109
+ def cleanup():
110
+ for dir_path in temp_dirs:
111
+ try:
112
+ if os.path.exists(dir_path):
113
+ shutil.rmtree(dir_path)
114
+ print(f"Cleaned up temporary directory: {dir_path}")
115
+ except Exception as e:
116
+ print(f"Error cleaning up {dir_path}: {str(e)}")
117
+
118
+ return response
119
+
120
+ except Exception as e:
121
+ # Ensure cleanup in case of errors
122
+ for dir_path in temp_dirs:
123
+ try:
124
+ if os.path.exists(dir_path):
125
+ shutil.rmtree(dir_path)
126
+ except:
127
+ pass # Best effort cleanup
128
+
129
+ print(f"Error in compression endpoint: {str(e)}")
130
+ return jsonify({"error": f"An error occurred: {str(e)}"}), 500
131
 
132
  if __name__ == "__main__":
133
+ app.run(host="0.0.0.0", port=7860)