当前位置: 首页 > news >正文

pyqt 上传文件或者文件夹打包压缩文件并添加密码并将密码和目标文件信息保存在json文件

一、完整代码实现

import sys
import os
import json
import pyzipper
from datetime import datetime
from PyQt5.QtWidgets import (QApplication, QWidget, QVBoxLayout, QHBoxLayout,
                             QPushButton, QLineEdit, QLabel, QFileDialog,
                             QMessageBox, QProgressBar)
from PyQt5.QtCore import Qt, QThread, pyqtSignal
from PyQt5.QtGui import QFont, QIcon

class ZipThread(QThread):
    progress = pyqtSignal(int)
    finished = pyqtSignal(str)
    error = pyqtSignal(str)

    def __init__(self, source, password, parent=None):
        super().__init__(parent)
        self.source = source
        self.password = password
        self.zip_path = f"{os.path.splitext(source)}_encrypted.zip"

    def run(self):
        try:
            total_files = self.calculate_total_files()
            processed = 0
            
            with pyzipper.AESZipFile(
                self.zip_path, 
                'w', 
                compression=pyzipper.ZIP_LZMA,
                encryption=pyzipper.WZ_AES
            ) as zf:
                zf.setpassword(self.password.encode())
                
                if os.path.isdir(self.source):
                    for root, dirs, files in os.walk(self.source):
                        for file in files:
                            full_path = os.path.join(root, file)
                            arcname = os.path.relpath(full_path, start=self.source)
                            zf.write(full_path, arcname)
                            processed += 1
                            self.progress.emit(int((processed/total_files)*100))
                else:
                    zf.write(self.source, os.path.basename(self.source))
                    self.progress.emit(100)
            
            self.save_metadata()
            self.finished.emit(self.zip_path)
            
        except Exception as e:
            self.error.emit(str(e))

    def calculate_total_files(self):
        if os.path.isfile(self.source):
            return 1
        count = 0
        for root, dirs, files in os.walk(self.source):
            count += len(files)
        return count

    def save_metadata(self):
        metadata = {
            "timestamp": datetime.now().isoformat(),
            "source_path": self.source,
            "zip_path": self.zip_path,
            "file_size": os.path.getsize(self.zip_path),
            "algorithm": "AES-256"
        }
        with open(self.zip_path + ".json", 'w') as f:
            json.dump(metadata, f, indent=2)

class SecureZipApp(QWidget):
    def __init__(self):
        super().__init__()
        self.selected_path = ""
        self.initUI()
        self.applyStyles()

    def initUI(self):
        self.setWindowTitle('安全文件压缩器')
        self.setWindowIcon(QIcon('lock_icon.png'))
        self.setFixedSize(500, 400)

        # 界面组件
        self.title_label = QLabel("安全加密压缩工具")
        self.path_label = QLabel("已选路径:无")
        self.progress_bar = QProgressBar()
        self.status_label = QLabel("就绪")
        
        self.pwd_input = QLineEdit()
        self.pwd_input.setPlaceholderText("输入加密密码(至少8位)")
        self.pwd_input.setEchoMode(QLineEdit.Password)
        
        # 按钮组
        btn_layout = QHBoxLayout()
        self.file_btn = QPushButton("📁 选择文件")
        self.dir_btn = QPushButton("📂 选择文件夹")
        self.start_btn = QPushButton("🔒 开始加密压缩")
        
        # 布局设置
        main_layout = QVBoxLayout()
        main_layout.addWidget(self.title_label, alignment=Qt.AlignCenter)
        main_layout.addSpacing(20)
        main_layout.addWidget(self.path_label)
        main_layout.addWidget(self.pwd_input)
        main_layout.addSpacing(15)
        
        btn_layout.addWidget(self.file_btn)
        btn_layout.addWidget(self.dir_btn)
        main_layout.addLayout(btn_layout)
        
        main_layout.addSpacing(30)
        main_layout.addWidget(self.progress_bar)
        main_layout.addWidget(self.status_label)
        main_layout.addWidget(self.start_btn)
        
        self.setLayout(main_layout)

        # 信号连接
        self.file_btn.clicked.connect(self.select_file)
        self.dir_btn.clicked.connect(self.select_dir)
        self.start_btn.clicked.connect(self.start_compression)

    def applyStyles(self):
        self.setStyleSheet("""\
            QWidget {\
                background-color: #F5F7FA;\
                font-family: 'Segoe UI';\
            }\
            QLabel#title_label {\
                font-size: 24px;\
                color: #2C3E50;\
                font-weight: bold;\
            }\
            QPushButton {\
                background-color: #4CAF50;\
                color: white;\
                border: none;\
                padding: 10px 20px;\
                border-radius: 5px;\
                font-size: 14px;\
            }\
            QPushButton:hover {\
                background-color: #45a049;\
            }\
            QLineEdit {\
                padding: 8px;\
                border: 2px solid #BDC3C7;\
                border-radius: 4px;\
                font-size: 14px;\
            }\
            QProgressBar {\
                height: 20px;\
                text-align: center;\
                border: 2px solid #BDC3C7;\
                border-radius: 5px;\
            }\
            QProgressBar::chunk {\
                background-color: #4CAF50;\
                width: 10px;\
            }\
        """)
        self.title_label.setObjectName("title_label")
        self.title_label.setFont(QFont("Arial", 16, QFont.Bold))
        self.status_label.setStyleSheet("color: #7F8C8D; font-size: 12px;")

    def select_file(self):
        path, _ = QFileDialog.getOpenFileName(self, "选择文件")
        if path:
            self.selected_path = path
            self.path_label.setText(f"已选文件:{os.path.basename(path)}")
            self.status_label.setText("就绪")

    def select_dir(self):
        path = QFileDialog.getExistingDirectory(self, "选择文件夹")
        if path:
            self.selected_path = path
            self.path_label.setText(f"已选文件夹:{os.path.basename(path)}")
            self.status_label.setText("就绪")

    def start_compression(self):
        if not self.selected_path:
            QMessageBox.warning(self, "警告", "请先选择文件或文件夹")
            return
        if len(self.pwd_input.text()) < 8:
            QMessageBox.warning(self, "警告", "密码长度至少8位")
            return

        self.thread = ZipThread(self.selected_path, self.pwd_input.text())
        self.thread.progress.connect(self.update_progress)
        self.thread.finished.connect(self.on_success)
        self.thread.error.connect(self.on_error)
        self.thread.start()
        self.start_btn.setEnabled(False)
        self.status_label.setText("正在压缩...")

    def update_progress(self, value):
        self.progress_bar.setValue(value)

    def on_success(self, zip_path):
        self.start_btn.setEnabled(True)
        self.status_label.setText("操作完成")
        QMessageBox.information(self, "成功", 
            f"加密压缩完成!\n保存路径:{zip_path}\n元数据文件:{zip_path}.json")

    def on_error(self, message):
        self.start_btn.setEnabled(True)
        self.status_label.setText("操作失败")
        QMessageBox.critical(self, "错误", f"发生错误:{message}")

if __name__ == '__main__':
    app = QApplication(sys.argv)
    window = SecureZipApp()
    window.show()
    sys.exit(app.exec_())

二、界面美化特色

  1. 现代UI设计

    • 采用扁平化设计风格
    • 使用系统图标符号(📁📂🔒)提升直观性
    • 自定义QSS样式表实现渐变按钮和圆角边框
  2. 交互优化

    • 实时路径显示
    • 动态进度条反馈
    • 状态标签提示当前操作阶段
    • 按钮禁用状态防止重复操作
  3. 安全增强

    • 密码强度验证(至少8位)
    • 密码输入掩码显示
    • 元数据文件独立存储(避免密码泄露)
  4. 响应式布局

    • 固定窗口尺寸防止变形
    • 智能间距控制
    • 组件对齐优化

三、使用说明

  1. 选择文件/文件夹
  2. 输入8位以上加密密码
  3. 点击加密压缩按钮
  4. 查看生成的.zip文件和同名的.json元数据文件

由小艺AI生成<xiaoyi.huawei.com>

相关文章:

  • ccf3401矩阵重塑(其一)
  • 使用Ajax技术进行动态网页的爬虫(pycharm)
  • Linux驱动学习笔记(二)
  • 工作记录 2017-01-25
  • FlinkCDC 达梦数据库实时同步详解
  • 酵母生产二氢槲皮素-文献精读117
  • C++基础系列【24】STL迭代器和算法
  • 基于金融产品深度学习推荐算法详解【附源码】
  • 计算机视觉常见的算法
  • JSON数据格式介绍
  • 蓝耘智算|从静态到动态:探索Maas平台海螺AI图片生成视频功能的强大能力
  • 移动端开发基础与常见布局
  • 网络安全一CTF入门
  • Vala教程-第一个程序(Hello world)
  • Python 视频爬取教程
  • 【通义千问】蓝耘智算 | 智启未来:蓝耘MaaS×通义QwQ-32B引领AI开发生产力
  • Blender选择循环边/循环面技巧
  • 【失败了】LazyGraphRAG利用本地ollama提供Embedding model服务和火山引擎的deepseek API构建本地知识库
  • 计算机操作系统(5)
  • Zabbix安装(保姆级教程)
  • 菲律宾中期选举结果揭晓,马科斯与杜特尔特家族重回“权力的游戏”
  • 东部沿海大省浙江,为何盯上内河航运?
  • 七猫征文大赛颁出112万奖金,非遗题材作品斩获金奖
  • 吉利汽车一季度净利润大增264%,称整合极氪后实现整体效益超5%
  • 魔都眼|锦江乐园摩天轮“换代”开拆,新摩天轮暂定118米
  • 遭“特朗普关税”冲击,韩国今年经济增长预期“腰斩”降至0.8%