基于Python搭建局域網(wǎng)大文件分享傳輸工具
1.簡(jiǎn)介
由于單位不讓用優(yōu)盤、禁止用飛秋、也不準(zhǔn)使共享,禁用FTP,也禁止搭建網(wǎng)站,且目前局域網(wǎng)內(nèi)用的IM不支持1G以上文件傳輸,于是在找適合內(nèi)網(wǎng)的大文件傳輸方法。開始搭建網(wǎng)盤,但上傳一次、下載一次,效率還是有點(diǎn)低。后來用Everything的HTTP服務(wù)器,結(jié)果把整個(gè)硬盤都分享了,太不安全。于是就自己做了這個(gè)簡(jiǎn)單的文件分享工具。資源已打包可自行下載。
HTTP分享,利用Flask搭建了一個(gè)Web服務(wù)器,選擇要分享的文件啟動(dòng)后,將生成的鏈接發(fā)給對(duì)方,對(duì)方就可以通過瀏覽器下載。
FTP分享用pyftpdlib搭建了一個(gè)FTP服務(wù)器,同樣生成鏈接后,對(duì)方可以通過一些瀏覽器或FTP客戶端下載,也可以通過程序提供的工具下載文件。
2.運(yùn)行效果
3.相關(guān)源碼
from PyQt5.QtWidgets import QApplication, QRadioButton, QMainWindow, QLabel, QComboBox, QLineEdit, QPushButton, QMessageBox, QToolButton, QFileDialog, QDialog from PyQt5.QtCore import QDir, Qt, QThread, pyqtSignal from PyQt5 import QtGui, QtCore, QtWidgets from PyQt5.QtGui import QIcon,QFont import sys import os import random import netifaces from flask import Flask, send_file from concurrent.futures import ThreadPoolExecutor from pyftpdlib.authorizers import DummyAuthorizer from pyftpdlib.handlers import FTPHandler from pyftpdlib.servers import ThreadedFTPServer from ftplib import FTP from urllib.parse import urlparse class HelpWindow(QDialog): def __init__(self): super().__init__() self.setWindowTitle("幫助") self.setFixedSize(300, 280) self.center() self.setWindowFlags(Qt.WindowCloseButtonHint | Qt.WindowTitleHint) self.label = QLabel(self) self.label.setText("1、選擇文件傳輸協(xié)議;2、輸入端口號(hào)(建議10000~60000,一般默認(rèn)即可); \ 3、選擇文件所在目錄;4、選擇要分享的文件;5、點(diǎn)擊啟動(dòng)按鈕,\ 若防火墻彈出警示點(diǎn)擊允許訪問即可;6、將生成的鏈接復(fù)制發(fā)送給接收方, \ 接收方通過瀏覽器訪問即可下載。若通過FTP協(xié)議分享還可通過FTP客戶端軟件 \ 或本程序的“接收FTP文件”按鈕下載。注意:傳輸完成后請(qǐng)及時(shí)關(guān)閉程序, \ 以免造成數(shù)據(jù)泄露和網(wǎng)絡(luò)安全隱患。") self.label.setGeometry(10, 10, 280, 260) self.label.setWordWrap(True) font = QFont() font.setPointSize(10) font.setBold(True) self.label.setFont(font) def center(self): screen = QApplication.desktop().screenGeometry() window = self.geometry() x = (screen.width() - window.width()) // 2 y = (screen.height() - window.height()) // 2 self.move(x, y) class DownloadThread(QThread): finished = pyqtSignal(bool) ftp = FTP() def __init__(self, ftp_url): super().__init__() self.ftp_url = ftp_url def run(self): parsed_url = urlparse(self.ftp_url) username = parsed_url.username password = parsed_url.password host = parsed_url.hostname port = parsed_url.port filename = parsed_url.path.rsplit('/', 1)[-1] if len(filename)==0: downloadfile = False else: downloadfile = True try: self.ftp.connect(host, port) self.ftp.encoding = 'utf-8' self.ftp.login(user=username, passwd=password) current_dir = os.getcwd() current_dir = current_dir.replace("\\", "/") random_int = random.randint(100, 999) mulu = "接收文件_" + str(random_int) LocalDir = current_dir + "/" + mulu if not os.path.exists(LocalDir): os.makedirs(LocalDir) if downloadfile:#下載一個(gè)文件 Local = os.path.join(LocalDir, filename) self.DownLoadFile(Local,filename) else:#下載整個(gè)目錄 self.DownLoadFileTree(LocalDir,"/") self.ftp.quit() self.finished.emit(True) except Exception as e: self.finished.emit(False) def DownLoadFile(self, LocalFile, RemoteFile): # 下載單個(gè)文件 with open(LocalFile, 'wb') as file_handler: self.ftp.retrbinary('RETR ' + RemoteFile, file_handler.write) file_handler.close() return True def DownLoadFileTree(self, LocalDir, RemoteDir): # 下載整個(gè)目錄下的文件 print("遠(yuǎn)程文件夾remoteDir:", RemoteDir) if not os.path.exists(LocalDir): os.makedirs(LocalDir) self.ftp.cwd(RemoteDir) RemoteNames = self.ftp.nlst() print("遠(yuǎn)程文件目錄:", RemoteNames) for file in RemoteNames: Local = os.path.join(LocalDir, file) #print("正在下載", self.ftp.nlst(file)) try: self.ftp.cwd(file) self.ftp.cwd("..") if not os.path.exists(Local): os.makedirs(Local) self.DownLoadFileTree(Local, file) except: self.DownLoadFile(Local, file) self.ftp.cwd("..") return class FTPWindow(QDialog): def __init__(self, parent=None): super().__init__(parent) self.setWindowTitle("下載FTP文件") self.setFixedSize(400, 150) self.label_ftp_url = QLabel("FTP鏈接:", self) self.label_ftp_url.setGeometry(20, 20, 80, 30) self.textbox_ftp_url = QLineEdit(self) self.textbox_ftp_url.setGeometry(100, 20, 280, 30) self.button_download = QPushButton("下載", self) self.button_download.setGeometry(160, 65, 80, 30) self.button_download.clicked.connect(self.download_ftp_file) self.label_ftp_info = QLabel("輸入包含文件名的鏈接下載指定文件;\n輸入不包含文件名只到端口號(hào)的鏈接下載整個(gè)目錄。", self) self.label_ftp_info.setGeometry(20, 110, 380, 40) def download_ftp_file(self): ftp_url = self.textbox_ftp_url.text() if ftp_url == "": return self.button_download.setEnabled(False) self.thread = DownloadThread(ftp_url) self.thread.finished.connect(self.show_message_box) self.thread.start() def show_message_box(self, success): if success: QMessageBox.information(self, "提示", "文件下載成功!", QMessageBox.Ok) else: QMessageBox.critical(self, "錯(cuò)誤", "文件下載失敗!", QMessageBox.Ok) self.button_download.setEnabled(True) class MyWindow(QMainWindow): def __init__(self): super().__init__() self.setWindowTitle("文件分享") self.setWindowIcon(QIcon('icon.ico')) self.setMaximumSize(self.size()) self.setFixedSize(400, 300) self.tcp_label = QLabel('選擇傳輸方式:', self) self.tcp_label.move(20, 10) self.http_button = QRadioButton('HTTP', self) self.http_button.setChecked(True) self.http_button.move(150, 10) self.http_button.toggled.connect(self.onProtocolChanged) self.ftp_button = QRadioButton('FTP', self) self.ftp_button.move(250, 10) self.ftp_button.toggled.connect(self.onProtocolChanged) self.ip_label = QLabel('當(dāng)前IP地址:', self) self.ip_label.move(20, 40) self.ip_text = QLabel(self.get_wired_ip(), self) self.ip_text.setGeometry(120, 43, 250, 25) self.port_label = QLabel('端 口 :', self) self.port_label.move(20, 75) self.textbox = QLineEdit(self) self.textbox.setGeometry(80, 75, 300, 30) self.textbox.setValidator(QtGui.QIntValidator(10000, 65500)) self.textbox.setText(str(random.randint(10000, 65500))) self.folder_label = QLabel('文件夾:', self) self.folder_label.setGeometry(20, 115, 50, 30) self.textfol = QLineEdit(self) self.textfol.setGeometry(80, 115, 220, 30) self.textfol.setText(QDir.currentPath()) self.textfol.setReadOnly(True) self.folder_button = QPushButton('選擇文件夾', self) self.folder_button.setGeometry(300, 115, 80, 30) self.folder_button.clicked.connect(self.onFolderClicked) self.file_label = QLabel('文 件 :', self) self.file_label.setGeometry(20, 155, 50, 30) self.combobox = QComboBox(self) self.combobox.setGeometry(80, 155, 300, 30) self.updateFileList() self.updateFileList() self.button = QPushButton(self) self.button.setText("啟 動(dòng)") self.button.setGeometry(20, 195, 360, 30) self.button.clicked.connect(self.show_selection) self.textboxa = QLineEdit(self) self.textboxa.setGeometry(20, 235, 360, 30) self.textboxa.mousePressEvent = self.select_text self.hidden_button = QPushButton("接收\(chéng)nFTP\n文件", self) self.hidden_button.setVisible(False) self.hidden_button.setGeometry(320, 10, 60, 55) self.hidden_button.clicked.connect(self.show_ftp_window) self.labela = QLabel(self) self.labela.setText("@hvinsion") self.labela.setGeometry(320, 280, 360, 20) self.labelb = QPushButton(self) self.labelb.setText("說明") self.labelb.setToolTip("幫助") self.labelb.setGeometry(10, self.height() - 30, 30, 30) self.labelb.clicked.connect(self.open_help_window) self.help_window = HelpWindow() self.thread_pool = ThreadPoolExecutor(max_workers=5) def open_help_window(self): self.help_window.show() def select_text(self, event): self.textboxa.selectAll() self.textboxa.setFocus() def show_ftp_window(self): ftp_window = FTPWindow(self) ftp_window.exec_() def onProtocolChanged(self): if self.ftp_button.isChecked(): self.hidden_button.setVisible(True) else: self.hidden_button.setVisible(False) def onFolderClicked(self): m = QFileDialog.getExistingDirectory(self, "選取文件夾", QDir.currentPath()) self.textfol.setText(m) self.updateFileList() def updateFileList(self): folder_path = self.textfol.text() file_list = QDir(folder_path).entryList(QDir.Files) self.combobox.clear() self.combobox.addItems(file_list) def get_wired_ip(self): try: default_gateway = netifaces.gateways()['default'] if default_gateway and netifaces.AF_INET in default_gateway: routingNicName = default_gateway[netifaces.AF_INET][1] for interface in netifaces.interfaces(): if interface == routingNicName: routingIPAddr = netifaces.ifaddresses(interface).get(netifaces.AF_INET) if routingIPAddr: return routingIPAddr[0]['addr'] except (KeyError, IndexError): pass return "未找到物理網(wǎng)卡IP" def start_flask_server(self): app = Flask(__name__) @app.route('/download/<filename>', methods=['GET']) def download_file(filename): file_path = os.path.join(self.textfol.text(), filename) return send_file(file_path, as_attachment=True) port = int(self.textbox.text()) self.textbox.setText(str(random.randint(10000, 65500))) app.run(host='0.0.0.0', port=port, threaded=True) def start_ftp_server(self): authorizer = DummyAuthorizer() authorizer.add_user('a', 'a', self.textfol.text(), perm='elradfmwM') class CustomFTPHandler(FTPHandler): def on_file_received(self, file): pass def on_file_deleted(self, file): pass def on_rename(self, old_file, new_file): pass handler = CustomFTPHandler handler.authorizer = authorizer address = ('0.0.0.0', int(self.textbox.text())) server = ThreadedFTPServer(address, handler) self.thread_pool.submit(server.serve_forever) self.textbox.setText(str(random.randint(10000, 65500))) def show_selection(self): ip_address = self.get_wired_ip() port_text = self.textbox.text() if int(port_text)<10000: QMessageBox.critical(self, "警告", "請(qǐng)勿使用10000以下端口號(hào)!", QMessageBox.Ok) self.textbox.setText(str(random.randint(10000, 65500))) return selected_file = self.combobox.currentText() if self.http_button.isChecked(): self.thread_pool.submit(self.start_flask_server) self.textboxa.setText("http://" + ip_address + ":" + port_text + "/download/" + selected_file) elif self.ftp_button.isChecked(): self.thread_pool.submit(self.start_ftp_server) self.textboxa.setText("ftp://a:a@" + ip_address + ":" + port_text + "/" + selected_file) else: QMessageBox.warning(self, "警告", "請(qǐng)選擇傳輸方式!", QMessageBox.Ok) if __name__ == "__main__": app = QApplication(sys.argv) win = MyWindow() win.show() sys.exit(app.exec_())
到此這篇關(guān)于基于Python搭建局域網(wǎng)大文件分享傳輸工具的文章就介紹到這了,更多相關(guān)Python大文件傳輸內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
python發(fā)qq消息轟炸虐狗好友思路詳解(完整代碼)
因?yàn)槲业哪硞€(gè)好友在情人節(jié)的時(shí)候秀恩愛,所以我靈光一閃制作了qq消息轟炸并記錄了下來。本文給大家分享python發(fā)qq消息轟炸虐狗好友思路詳解,感興趣的朋友一起看看吧2020-02-02使用python matploblib庫(kù)繪制準(zhǔn)確率,損失率折線圖
這篇文章主要介紹了使用python matploblib庫(kù)繪制準(zhǔn)確率,損失率折線圖,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2020-06-06利用python計(jì)算windows全盤文件md5值的腳本
這篇文章主要介紹了利用python計(jì)算windows全盤文件md5值的腳本,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2019-07-07python+excel接口自動(dòng)化獲取token并作為請(qǐng)求參數(shù)進(jìn)行傳參操作
這篇文章主要介紹了python+excel接口自動(dòng)化獲取token并作為請(qǐng)求參數(shù)進(jìn)行傳參操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2020-11-11Python基于Socket實(shí)現(xiàn)簡(jiǎn)單聊天室
這篇文章主要為大家詳細(xì)介紹了Python基于Socket實(shí)現(xiàn)簡(jiǎn)單聊天室,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2020-02-02Python多進(jìn)程池 multiprocessing Pool用法示例
這篇文章主要介紹了Python多進(jìn)程池 multiprocessing Pool用法,結(jié)合實(shí)例形式分析了多進(jìn)程池 multiprocessing Pool相關(guān)概念、原理及簡(jiǎn)單使用技巧,需要的朋友可以參考下2018-09-09