Spaces:
Paused
Paused
File size: 4,979 Bytes
e68fc4b 611be2f 4c85f97 21bc43d e68fc4b 987d7c4 e68fc4b 4d04ed4 987d7c4 e68fc4b 4c85f97 679df68 72673b1 4c85f97 72673b1 4c85f97 39ae163 4c85f97 39ae163 e68fc4b 21bc43d 4c85f97 611be2f 52f175a 679df68 52f175a 611be2f 21bc43d 87d950a 21bc43d 87d950a e68fc4b 21bc43d 4c85f97 679df68 987d7c4 e68fc4b 4d04ed4 e68fc4b 4d04ed4 e68fc4b |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 |
import dash
from dash import dcc, html, Input, Output, State, callback
import dash_bootstrap_components as dbc
from dash.exceptions import PreventUpdate
import pikepdf
import requests
import io
import tempfile
import os
import base64
import threading
app = dash.Dash(__name__, external_stylesheets=[dbc.themes.BOOTSTRAP])
app.layout = dbc.Container([
html.H1("PDF Compressor", className="my-4"),
dbc.Card([
dbc.CardBody([
dcc.Upload(
id='upload-pdf',
children=html.Div([
'Drag and Drop or ',
html.A('Select PDF File')
]),
style={
'width': '100%',
'height': '60px',
'lineHeight': '60px',
'borderWidth': '1px',
'borderStyle': 'dashed',
'borderRadius': '5px',
'textAlign': 'center',
'margin': '10px'
},
multiple=False
),
dbc.Alert(id="upload-status", is_open=False, duration=4000, className="mt-3"),
dbc.Input(id="url-input", placeholder="Or enter PDF URL", type="text", className="mt-3"),
dbc.Button("Compress PDF", id="compress-btn", color="primary", className="mt-3"),
dbc.Spinner(
html.Div(id="compression-status", className="mt-3"),
color="primary",
type="border",
fullscreen=True,
fullscreen_style={"backgroundColor": "rgba(0, 0, 0, 0.3)"},
),
dcc.Download(id="download-pdf"),
])
]),
])
def compress_pdf(input_file, url):
if input_file is None and (url is None or url.strip() == ""):
return None, "Please provide either a file or a URL."
if input_file is not None and url and url.strip() != "":
return None, "Please provide either a file or a URL, not both."
try:
if url and url.strip() != "":
response = requests.get(url)
response.raise_for_status()
pdf_content = io.BytesIO(response.content)
initial_size = len(response.content)
else:
content_type, content_string = input_file.split(',')
decoded = base64.b64decode(content_string)
pdf_content = io.BytesIO(decoded)
initial_size = len(decoded)
with tempfile.NamedTemporaryFile(delete=False, suffix=".pdf") as temp_file:
temp_file_path = temp_file.name
pdf = pikepdf.Pdf.open(pdf_content)
compression_params = dict(compress_streams=True, object_stream_mode=pikepdf.ObjectStreamMode.generate)
pdf.save(temp_file_path, **compression_params)
compressed_size = os.path.getsize(temp_file_path)
compression_ratio = compressed_size / initial_size
compression_percentage = (1 - compression_ratio) * 100
if compression_ratio >= 1 or compression_percentage < 5:
os.remove(temp_file_path)
return None, f"Unable to compress the PDF effectively. Original file returned. (Attempted compression: {compression_percentage:.2f}%)"
return temp_file_path, f"PDF compressed successfully! Compression achieved: {compression_percentage:.2f}%"
except Exception as e:
return None, f"Error compressing PDF: {str(e)}"
@callback(
Output("upload-status", "children"),
Output("upload-status", "is_open"),
Output("upload-status", "color"),
Input("upload-pdf", "filename"),
Input("upload-pdf", "contents"),
)
def update_upload_status(filename, contents):
if filename is not None and contents is not None:
return f"File uploaded: {filename}", True, "success"
return "", False, "primary"
@callback(
Output("compression-status", "children"),
Output("download-pdf", "data"),
Input("compress-btn", "n_clicks"),
State("upload-pdf", "contents"),
State("url-input", "value"),
prevent_initial_call=True
)
def process_compress_and_download(n_clicks, file_content, url):
if file_content is None and (url is None or url.strip() == ""):
return "Please provide either a file or a URL.", None
def compression_thread():
nonlocal file_content, url
output_file, message = compress_pdf(file_content, url)
if output_file:
with open(output_file, "rb") as file:
compressed_content = file.read()
os.remove(output_file)
return message, dcc.send_bytes(compressed_content, "compressed.pdf")
else:
return message, None
thread = threading.Thread(target=compression_thread)
thread.start()
thread.join()
return compression_thread()
if __name__ == '__main__':
print("Starting the Dash application...")
app.run(debug=True, host='0.0.0.0', port=7860)
print("Dash application has finished running.") |