利用python+qt编写阿里云OSS文件管理系统下

  • 梦影无痕丶
  • 11 Minutes
  • March 12, 2018

前言

上篇博客介绍了环境的搭建与UI文件的实现,本篇博客接上篇介绍该系统的逻辑控制实现,包括文件的上传、下载、查看、删除,以及文件链接的 markdown 格式化。

代码实现

新建 appUI.py 文件。

在这里,需要用到QT控件,系统时间调用,以及之前编辑的UI文件。首先导入python

from PyQt5 import QtWidgets
from aliyunOSS import Ui_MainWindow
from aliyunManage import *
import time,sys

操作类实现

这里需要先定义一个类MainWindow。名字必须与之前文件的Ui_MainWindow窗体接口名字一样。

该类继承了QtWidgets中的QMainWindow类与aliyunOSS中的 Ui_MainWindow类,代码是这样的:

class MainWindow(QtWidgets.QMainWindow,Ui_MainWindow):

类的初始化

这里实现了窗口的初始化 setupUi 。获取系统时间,并存为 年-月-日 格式,获取时间的原因是后面根据日期自动生成上传文件夹的名字。用户信息的显示 fillUserState

def __init__(self, parent=None):
    super(MainWindow,self).__init__(parent)
    self.setupUi(self)
    self.targetFoldText.setText(time.strftime("%Y-%m-%d", time.localtime(time.time())))
    self.fillUserState()

用户属性界面

将用户信息填入文本框:

def fillUserState(self):
    self.jsondata=jsonOp()
    self.AccessKeyId.setText(self.jsondata.data['AccessKeyId'])
    self.AccessKeySecret.setText(self.jsondata.data['AccessKeySecret'])
    self.bucket.setText(self.jsondata.data['bucket'])
    self.EndPoint.setText(self.jsondata.data['EndPoint'])

响应用户属性界面的 保存 按钮,修改用户信息并写入json文件:

def changeUser(self):
    self.jsondata.data['AccessKeyId']=self.AccessKeyId.toPlainText()
    self.jsondata.data['AccessKeySecret']=self.AccessKeySecret.toPlainText()
    self.jsondata.data['bucket']=self.bucket.toPlainText()
    self.jsondata.data['EndPoint']=self.EndPoint.toPlainText()
    self.jsondata.write()

查看文件界面

响应 刷新 按钮,显示云端存储文件:

def getFile(self):
    self.ossItemsText.clear()
    oss=OSSOp()
    files=oss.showfile()
    for file in files:
        self.ossItemsText.addItem(file)

响应 选中文件 按钮,点击文件显示框中文件名触发,保存当前选择文件名,同时,在外网地址文本框中显示当前文件的网络地址。

这里解释下,在阿里云中:

文件的外网地址=http://+bucket名+.+EndPoint名+/+上传文件名

其中上传的文件名是包括文件路径名的。

def OSSfileSelect(self):
    self.OSSItemSelect=self.ossItemsText.currentItem()
    self.OSSFileAddrText.clear()
    self.OSSFileAddrText.insertPlainText('http://'+self.jsondata.data['bucket']+'.'+self.jsondata.data['EndPoint']+'/'+self.OSSItemSelect.text())

响应 markdown 按钮,将文件外网地址转为 markdown 的图片插入格式:

def showMarkdown(self):
    name=self.OSSFileAddrText.toPlainText()
    self.OSSFileAddrText.clear()
    self.OSSFileAddrText.insertPlainText('![]('+name+')')

响应 删除文件 按钮,先检查是否选中文件,否则弹出 未选中文件 窗口,删除成功后刷新文件显示框:

def deleteFile(self):
    oss=OSSOp()
    try:
        if len(self.OSSItemSelect.text()):
            if oss.deletefile(self.OSSItemSelect.text())==True:
                self.getFile()
        else:
            QtWidgets.QMessageBox.information(None, 'Message', '未选中文件',QtWidgets.QMessageBox.Yes)
    except AttributeError as e:
        QtWidgets.QMessageBox.information(None, 'Message', '未选中文件',QtWidgets.QMessageBox.Yes)

响应 下载文件 按钮,这里需要先点击文件显示框中的文件,否则会弹出未选中文件的提示:

def downloadFile(self):
    oss=OSSOp()
    try:
        if len(self.OSSItemSelect.text()):
            file_name,path =  QtWidgets.QFileDialog.getSaveFileName(self,"save file","" ,"all files(*.*)")   
            if oss.downloadfile(self.OSSItemSelect.text(),file_name)==True:
                QtWidgets.QMessageBox.information(None, 'Message', '下载成功',QtWidgets.QMessageBox.Yes)
        else:
            QtWidgets.QMessageBox.information(None, 'Message', '未选中文件',QtWidgets.QMessageBox.Yes)
    except AttributeError as e:
        QtWidgets.QMessageBox.information(None, 'Message', '未选中文件',QtWidgets.QMessageBox.Yes)

上传文件界面

响应 选择文件 按钮,调用系统的文件浏览器,选中文件后会在右方文本框显示所选文件。

def selectFile(self):
    files, filetype = QtWidgets.QFileDialog.getOpenFileNames(None,"文件选择","","All Files (*)")
    self.selectText.clear()
    for name in files:
        self.selectText.insertPlainText(name+'\n')

这里使用了 QtWidgets.QFileDialog.getOpenFileNames 可选择多个文件。

这里列下关于QT的文件选择函数

函数名 用处
getExistingDirectory 选择文件夹
getOpenFileName 选择单个文件
getOpenFileNames 选择多个文件
getSaveFileName 保存文件

具体用法,以 getOpenFileNames 为例,其他函数一样,

files, filetype = QtWidgets.QFileDialog.getOpenFileNames(None,"文件选择","","All Files (*)")

第一个参数是父窗口名,直接用None,表示无父窗口;

第二个参数是窗口的名字,任写;

第三个是打开的文件浏览器路径,空 表示打开上次打开的文件夹,若是第一次打开则打开程序所在文件夹;

第四个表示文件打开的类型,All Files(*)表示所有类型。

响应 上传文件 按钮:

def uploadFile(self):
    oss=OSSOp()
    files=self.selectText.toPlainText()
    self.targetFileAddrText.clear()
    if len(files)!=0:
        fileName=files.split('\n')[:-1]
        for file in fileName:
            result=file.split('/')
            res=result[len(result)-1]
            fold=self.targetFoldText.toPlainText()
            if fold!='':
                fold+='/'
            if oss.putfile(fold+res,file)==False:
                QtWidgets.QMessageBox.information(None, 'Message', '文件'+res+'上传失败',QtWidgets.QMessageBox.Yes)
                return
            else:
                self.targetFileAddrText.insertPlainText('http://'+self.jsondata.data['bucket']+'.'+self.jsondata.data['EndPoint']+'/'+fold+res+'\n')
        QtWidgets.QMessageBox.information(None, 'Message', '文件上传成功',QtWidgets.QMessageBox.Yes)

    else:
        QtWidgets.QMessageBox.information(None, 'Message', '未选中文件',QtWidgets.QMessageBox.Yes)

由于这里是可以支持文件多选的,先利用

files.split('\n')[:-1]

\n 为分割符分割字符串,这里得到的最后一个字符串是空字符串,使用[:-1] 舍弃。

得到的文件名是包括路径的,我们需要获取单独的文件名,继续利用file.split(‘/‘)分割字符,字符串集合的最后一个是文件名。

将目标文件文本框内容与文件名组合成上传文件名,使用 oss.putfile 函数上传。

上传文件地址markdown格式化:

def uploadMarkdown(self):
    names=self.targetFileAddrText.toPlainText()
    self.targetFileAddrText.clear()
    if len(names)!=0:
        name=names.split('\n')[:-1]
        for item in name:
            self.targetFileAddrText.insertPlainText('![]('+item+')\n')

主函数

if __name__ == "__main__":
    app = QtWidgets.QApplication(sys.argv)
    window = MainWindow()
    window.show()
    sys.exit(app.exec_())

打包成 EXE 文件

这里一定要先选中 appUI.py 文件,这个是启动文件,然后点击 工具->pyinstaller,等待完成即可,然后在项目文件夹中会生成 build 和dist 两个文件夹。其中,build 目录是 pyinstaller 存储临时文件的目录,可以直接删除。dist 文件夹存放生成的 exe 文件,将 data.json 文件拷入,即可运行了。

这里在使用 pyinstaller 还遇到一个错误,是在 pyinstaller输出窗口报错:

module 'enum' has no attribute 'IntFlag'?

查阅 stack overflow 得到了解决方案,原因是使用了 enum34 这个库,而这个库在 python3.4 以上的版本已经弃用了,直接用pip卸载:

pip uninstall enum34

总结

这个管理系统算是我用python+qt做的第一个界面程序,由于也是对qt不熟悉,功能基本都是拼凑出来的,bug这东西,当然一大堆了。功能也不够完善,目前只是在写 markdown 博客时上传云端图片使用。
好在各个模块的功能是相对独立的,后续还有什么功能的需要的话可以直接在里面添加就行。