1. Requirements
The company wants to make an H5 mobile adapter page. Because of technical problems, H5 is outsourced. Each time the front-end gives us the source code, we pass the source code to the server for others to access to see if there is a bug. Isn't that troublesome?Some people say that they can let the front end be hosted on their servers first, and the source code will not end after we have checked it, yeah!Everyone wants this, but...
Is it better to have direct access to the local environment?The problem is that our program doesn't have time to dock with the H5 front end at this time, which wastes both our time and theirs.So develop a service server with testers directly involved so that we can divide up our work perfectly.
2. Python Build web Server
Python comes with an http.serrver package that makes it easy to set up a web server
Official website: https://docs.python.org/3/library/http.server.html?highlight=httpserver#http.server.BaseHTTPRequestHandler
Reference resources:
http://www.cnblogs.com/xuxn/archive/2011/02/14/build-simple-web-server-with-python.html
http://blog.csdn.net/kevin_darkelf/article/details/40979545
http://blog.csdn.net/tianmohust/article/details/7689414
# return Html page class MyHttpBaseHandler(BaseHTTPRequestHandler): def do_GET(self): print(self.path) enc = "UTF-8" encoded = ''.join(self.path).encode(enc) f = io.BytesIO() f.write(encoded) f.seek(0) self.send_response(200) self.send_header("Content-type", "text/html; charset=%s" % enc) self.send_header("Content-Length", str(len(encoded))) self.end_headers() shutil.copyfileobj(f, self.wfile) # This method serves the 'POST' request type, only allowed for CGI scripts. def do_POST(self): pass # return static -m eg:python -m http.server 8080 class MyHttpSimpleHandler(SimpleHTTPRequestHandler): pass
httpd = HTTPServer((self.addressIP, self.port), MyHttpSimpleHandler)
print("Server started on " + self.addressIP + ",port " + str(self.port) + ".....")
httpd.serve_forever()
3. Draw UI and generate QR code
Written before
Pyqt+QRcode to generate recognition QR codes
Direct Reference Generation of 2D Codes
Draw UI
class MainWidgetUI(QDialog): def __init__(self, parent=None): super(MainWidgetUI, self).__init__(parent) self.setFixedSize(640, 480) # PyQT Disable window resizing self.setWindowTitle('Python Create a local server environment to generate QR codes') self.setWindowIcon(QtGui.QIcon("favicon.ico")) # Main layout main_layout = QVBoxLayout() self.methodtype = QComboBox() self.methodTopLayout = QHBoxLayout() self.methodtype.addItem('file', QVariant(1)) # Use QVariant Preservation Key self.methodtype.addItem('address', QVariant(2)) self.methodtype.setFixedWidth(90) # Set fixed width to 90 px self.pushButton = QPushButton("Select File") self.Url = QLineEdit() self.Url.hide() self.methodTopLayout.addWidget(self.methodtype) # Add a widget self.methodTopLayout.addWidget(self.Url) # Add a widget self.methodTopLayout.addSpacing(10) # Add a 10 px Spatial distance without elasticity self.methodTopLayout.addWidget(self.pushButton) self.qrcodeGroup = QVBoxLayout() self.groupBox = QGroupBox("QR code") self.QrLabel = QLabel(self.groupBox) self.qrcodeGroup.addWidget(self.groupBox) main_layout.addLayout(self.methodTopLayout) # Add a layout main_layout.addLayout(self.qrcodeGroup) self.setLayout(main_layout) self.QrLabel.setGeometry(QRect(30, 30, 540, 380)) # Set up qrLabel Graphic Position # self.QrLabel.setScaledContents(True) # Scale 2D code display self.pushButton.clicked.connect(self.FileOperator) # Click the button self.methodtype.currentIndexChanged.connect(self.comboxchange) # Events when drop-down box changes self.Url.textChanged.connect(self.comboxchange) # Triggered when the contents of the address text box change
Generate two-dimensional code
# Get the server (address) to generate the QR code def ShowQrCode(self, strings): if not strings: # The parameter is empty, pixmap Is empty self.QrLabel.setPixmap(QtGui.QPixmap("")) else: qr = qrcode.QRCode(version=None, error_correction=qrcode.constants.ERROR_CORRECT_L, box_size=10, border=2, ) qr.add_data(strings) qr.make(fit=True) img = qr.make_image() qraddr=tempDir+'qr.png' print(qraddr) img.save(qraddr)
Simply, by choosing the file get path, copy the file to the current directory, set the current directory to the http.server service directory, and use the QR code as the service address + file name
4. Matters needing attention
1. Get the current LAN IP
addressIP = socket.gethostbyname_ex(socket.gethostname())[-1][0] # Get LAN IP
2. Get the temporary directory for windows
tempDir = tempfile.gettempdir() + '/' # Get Temporary temp Catalog
3. copy file
There are two types of copy files, one that comes with Python and the other that comes with Pyqt
shutil.copy(filePath, "./") # file=>Catalog
QFile.copy(filePath, sys.path[0]+"\\"+file) # QFile.copy Must file pair=>file
4. Use threads to open services
Opening httpd.serve_forever() directly in the UI can cause UI congestion, so use the QtCore.QThread thread to open the http service
5. Dynamically resize the UI
Different parameters result in different QR code sizes, so modify the UI size dynamically to display the entire QR code
qrsize = Image.open(qraddr).size if qrsize[0] > 400: # Modify the size of the form dynamically when the 2-D code has a pixel value greater than 400 dsize = qrsize[0] // 2 # Integer part self.setFixedSize(640 + dsize, 480 + dsize) self.QrLabel.setGeometry(QRect(30, 30, 540 + dsize, 380 + dsize)) else: self.setFixedSize(640, 480) self.QrLabel.setGeometry(QRect(30, 30, 540, 380)) self.QrLabel.setPixmap(QtGui.QPixmap(qraddr))
6. Determine if the file's md5 comparison file is the latest version
if filePath: file = filePath.split('/')[-1] isfExist = os.path.exists(file) if not isfExist: # No file exists shutil.copy(filePath, "./") # File pairs=>Catalog else: # Files already exist, compare files md5 Determine whether it is the latest file md5FilePath = self.getFileMD5(filePath) md5File = self.getFileMD5(file) if md5File != md5FilePath: shutil.copy(filePath, "./") # Getting Files MD5 Value, for small files def getFileMD5(self, filepath): f = open(filepath, 'rb') md5obj = hashlib.md5() md5obj.update(f.read()) hash = md5obj.hexdigest() f.close() return str(hash).upper()
7. Generate debug.log log log
def delog(string='--'): debugFile=open("debog.txt",'a',1,'utf-8') debugFile.writelines(string+'\n') debugFile.close()
5. Complete Code
# -*- coding: UTF8 -*- import io, shutil, sys, os from http.server import HTTPServer, BaseHTTPRequestHandler, SimpleHTTPRequestHandler from PyQt5.QtWidgets import * from PyQt5.QtCore import * from PyQt5 import QtGui import qrcode from PIL import Image import socket import hashlib import tempfile port = 8080 # Default Port addressIP = socket.gethostbyname_ex(socket.gethostname())[-1][0] # Get LAN IP tempDir = tempfile.gettempdir() + '/' # Get Temporary temp Catalog class MainWidgetUI(QDialog): def __init__(self, parent=None): super(MainWidgetUI, self).__init__(parent) self.setFixedSize(640, 480) # PyQT Disable window resizing self.setWindowTitle('Python Create a local server environment to generate QR codes') self.setWindowIcon(QtGui.QIcon("favicon.ico")) # Main layout main_layout = QVBoxLayout() self.methodtype = QComboBox() self.methodTopLayout = QHBoxLayout() self.methodtype.addItem('file', QVariant(1)) # Use QVariant Preservation Key self.methodtype.addItem('address', QVariant(2)) self.methodtype.setFixedWidth(90) # Set fixed width to 90 px self.pushButton = QPushButton("Select File") self.Url = QLineEdit() self.Url.hide() self.methodTopLayout.addWidget(self.methodtype) # Add a widget self.methodTopLayout.addWidget(self.Url) # Add a widget self.methodTopLayout.addSpacing(10) # Add a 10 px Spatial distance without elasticity self.methodTopLayout.addWidget(self.pushButton) self.qrcodeGroup = QVBoxLayout() self.groupBox = QGroupBox("QR code") self.QrLabel = QLabel(self.groupBox) self.qrcodeGroup.addWidget(self.groupBox) main_layout.addLayout(self.methodTopLayout) # Add a layout main_layout.addLayout(self.qrcodeGroup) self.setLayout(main_layout) self.QrLabel.setGeometry(QRect(30, 30, 540, 380)) # Set up qrLabel Graphic Position # self.QrLabel.setScaledContents(True) # Scale 2D code display self.pushButton.clicked.connect(self.FileOperator) # Click the button self.methodtype.currentIndexChanged.connect(self.comboxchange) # Events when drop-down box changes self.Url.textChanged.connect(self.comboxchange) # Triggered when the contents of the address text box change # File Operation def FileOperator(self): filePath = self.selectFile() if filePath: file = filePath.split('/')[-1] isfExist = os.path.exists(file) if not isfExist: # No file exists shutil.copy(filePath, "./") # File pairs=>Catalog # delog(a) # Package exe debug log # QFile.copy(filePath, sys.path[0]+"\\"+file) QFile.copy Must file pair=>file else: # Files already exist, compare files md5 Determine whether it is the latest file md5FilePath = self.getFileMD5(filePath) md5File = self.getFileMD5(file) if md5File != md5FilePath: shutil.copy(filePath, "./") # Spliced 2D Code Parameters address = "http://" + addressIP + ':' + str(port) + '/' + file self.ShowQrCode(address) # Display QR Code print('generate qrcord') self.Theading = TheadingPost((addressIP, port)) # Open process Open service-Direct Start http.service Causes UI Process not responding self.Theading.start() # Thread Start # Getting Files MD5 Value, for small files def getFileMD5(self, filepath): f = open(filepath, 'rb') md5obj = hashlib.md5() md5obj.update(f.read()) hash = md5obj.hexdigest() f.close() return str(hash).upper() # Select File def selectFile(self): # getOpenFileName Only one can be selected getOpenFileNames Multiple choices files = QFileDialog.getOpenFileName(self, "Please select a playback file", '', "*.*") if files[0] == '': QMessageBox.warning(self, u'Error tip!', "Please select a file", QMessageBox.Yes) else: return files[0] # Drop-down box selection def comboxchange(self): currentIndex = self.methodtype.currentIndex() # currentIndex Index increases from 0 key = self.methodtype.itemData(currentIndex) # QVariant Saved key # self.methodtype.currentText() # text if key == 1: # file self.pushButton.show() self.Url.hide() self.ShowQrCode("") elif key == 2: # address self.pushButton.hide() self.Url.show() url = self.Url.text() self.ShowQrCode(url) # Get Server (Address) Generate QR Code 12 def ShowQrCode(self, strings): if not strings: # The parameter is empty, pixmap Is empty self.QrLabel.setPixmap(QtGui.QPixmap("")) else: qr = qrcode.QRCode(version=None, error_correction=qrcode.constants.ERROR_CORRECT_L, box_size=10, border=2, ) qr.add_data(strings) qr.make(fit=True) img = qr.make_image() qraddr=tempDir+'qr.png' print(qraddr) img.save(qraddr) qrsize = Image.open(qraddr).size if qrsize[0] > 400: # Modify the size of the form dynamically when the 2-D code has a pixel value greater than 400 dsize = qrsize[0] // 2 # Integer part self.setFixedSize(640 + dsize, 480 + dsize) self.QrLabel.setGeometry(QRect(30, 30, 540 + dsize, 380 + dsize)) else: self.setFixedSize(640, 480) self.QrLabel.setGeometry(QRect(30, 30, 540, 380)) self.QrLabel.setPixmap(QtGui.QPixmap(qraddr)) # return Html page class MyHttpBaseHandler(BaseHTTPRequestHandler): def do_GET(self): print(self.path) enc = "UTF-8" encoded = ''.join(self.path).encode(enc) f = io.BytesIO() f.write(encoded) f.seek(0) self.send_response(200) self.send_header("Content-type", "text/html; charset=%s" % enc) self.send_header("Content-Length", str(len(encoded))) self.end_headers() shutil.copyfileobj(f, self.wfile) # This method serves the 'POST' request type, only allowed for CGI scripts. def do_POST(self): pass # return static -m eg:python -m http.server 8080 class MyHttpSimpleHandler(SimpleHTTPRequestHandler): pass # Start Services class TheadingPost(QThread): def __init__(self, list): super(TheadingPost, self).__init__() self.addressIP = list[0] self.port = list[1] def run(self): httpd = HTTPServer((self.addressIP, self.port), MyHttpSimpleHandler) print("Server started on " + self.addressIP + ",port " + str(self.port) + ".....") httpd.serve_forever() def delog(string='--'): debugFile=open("debog.txt",'a',1,'utf-8') debugFile.writelines(string+'\n') debugFile.close() if __name__ == "__main__": app = QApplication(sys.argv) main_widget = MainWidgetUI() main_widget.show() sys.exit(app.exec_())