/
Ig.Ro
/
PDF_View
Обзор
Документация
Войти
/
Ig.Ro
/
PDF_View
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
CI/CD
Аналитика
Безопасность
master
render_worker.py
112 строк
5 KB
Ig.Ro
upload files
14 янв 2026, 16:44
14 янв 2026, 16:44
2d33e26
Код
Авторство
О чём код?
import os import tempfile import shutil import logging from PyQt6.QtCore import QObject, pyqtSignal from PyQt6.QtGui import QImage from pdf2image import convert_from_path import fitz import utils logger = logging.getLogger("PDFViewer") class PDFRenderWorker(QObject): finished = pyqtSignal(list, str, int) page_rendered = pyqtSignal(int, QImage) error = pyqtSignal(str) progress = pyqtSignal(int) def render(self, file_path: str, poppler_path: str = None, cache_pages: bool = True, page_range: tuple = None): temp_file = None try: if not os.path.isfile(file_path): raise FileNotFoundError(f"Файл не найден: {file_path}") src_size = os.path.getsize(file_path) if src_size == 0: raise ValueError("Исходный PDF-файл пуст") if src_size > utils.MAX_PDF_FILE_SIZE: raise ValueError("Файл слишком большой") logger.debug(f"Исходный файл: {file_path}, размер: {src_size} байт") with tempfile.NamedTemporaryFile(delete=False, suffix=".pdf") as tmp: temp_file = tmp.name shutil.copy2(file_path, temp_file) dst_size = os.path.getsize(temp_file) logger.debug(f"Временный файл: {temp_file}, размер: {dst_size} байт") if dst_size != src_size: import time for attempt in range(3): logger.debug(f"Размер не совпадает. Попытка ожидания #{attempt + 1}") time.sleep(0.5) dst_size = os.path.getsize(temp_file) logger.debug(f"После ожидания: {dst_size} байт") if dst_size == src_size: break else: raise IOError( f"Размер временного файла ({dst_size}) не совпадает с исходным ({src_size}). " "Возможно, файл не полностью скопирован из-за медленного соединения." ) with open(temp_file, "rb") as f: header = f.read(4) if header != b"%PDF": raise ValueError("Скопированный файл не является валидным PDF (отсутствует сигнатура %PDF)") doc = fitz.open(temp_file) total_pages = doc.page_count doc.close() if page_range: start_page, end_page = page_range else: start_page = 1 end_page = total_pages start_page = max(1, min(start_page, total_pages)) end_page = max(start_page, min(end_page, total_pages)) kwargs = {"poppler_path": poppler_path} if poppler_path else {} images = [] for i in range(start_page, end_page + 1): try: page_images = convert_from_path(temp_file, first_page=i, last_page=i, dpi=utils.RENDER_DPI, **kwargs) if page_images: pil_img = page_images[0].convert("RGBA") data = pil_img.tobytes("raw", "RGBA") qimg = QImage(data, pil_img.width, pil_img.height, QImage.Format.Format_RGBA8888).copy() images.append(qimg) progress_percent = int((i - start_page + 1) / (end_page - start_page + 1) * 100) self.progress.emit(progress_percent) self.page_rendered.emit(i, qimg) except Exception as e: logger.error(f"Ошибка при рендеринге страницы {i}: {e}") empty_img = QImage(100, 100, QImage.Format.Format_RGBA8888) empty_img.fill(Qt.GlobalColor.white) images.append(empty_img) if not images: raise ValueError("PDF пуст или не содержит страниц") self.finished.emit(images, file_path, total_pages) except Exception as e: self.error.emit(f"{type(e).__name__}: {e}") finally: if temp_file and os.path.exists(temp_file): try: os.unlink(temp_file) except Exception as e: logger.warning(f"Не удалось удалить временный файл {temp_file}: {e}")