Skip to content

Instantly share code, notes, and snippets.

@mpco
Last active May 27, 2017 19:21
Show Gist options
  • Save mpco/b828cd763cce110df4d9ecb15e82214d to your computer and use it in GitHub Desktop.
Save mpco/b828cd763cce110df4d9ecb15e82214d to your computer and use it in GitHub Desktop.
利用Python建立本地服务器,二维码展示想要传输的文件网址,传输完成后自动关闭服务器,并删除二维码。
#!/usr/bin/env python
# -*- coding: UTF-8 -*-
# python 2.7
# request: `brew install qrencode`
# OS: macOS because using Applescript.
"""
Author: Mr.pc
Date: 20170528
Version: 1.1
Description:
利用Python建立本地服务器,二维码展示想要传输的文件网址。
传输完成后自动关闭服务器,并删除二维码。
如果在TIMEOUT的时间内没有进行传输,则自动关闭并删除二维码。
Todo:
目前的版本默认只传输一次文件。
在使用中,如果使用微信扫描二维码,会自动打开。
这时,无法再在其他App中打开二维码中网址。
"""
import SimpleHTTPServer
import SocketServer
import subprocess
import socket
import sys
import os
import random
PORT = 8000
# 传输完成标记
TransferCompleted = False
# seconds
TIMEOUT = 30
def randomFileName(length):
"""
生成随机的文件名
"""
return ''.join(random.choice("abcdefghijklmnopqrstuvwxyz") for i in range(length))
def displayQRcode(addr, filename):
"""
生成二维码并显示
"""
os.system("/usr/local/bin/qrencode -o '{}' '{}'".format(filename, addr))
os.system("open {}".format(filename))
def rmQRcode(filename):
"""
关闭二维码展示
并删除二维码图片
"""
os.system('osascript -e \'tell application "Preview" to close (every window whose name is \"' + os.path.basename(filename) + '\")\'')
os.system('osascript -e \'tell app "Finder" to move the POSIX file "' + filename + '" to trash\'')
def getLocalIP():
"""
获取本机的局域网IP
"""
proc = subprocess.Popen("""ifconfig | grep "inet.*0xffffff00" | awk {'print $2'}""", stdout=subprocess.PIPE, shell=True)
(out, err) = proc.communicate()
return out.strip()
def notify(title, text):
"""
发出系统提醒
"""
os.system("""
osascript -e 'display notification "{}" with title "{}"'
""".format(text, title))
class MyHandler(SimpleHTTPServer.SimpleHTTPRequestHandler):
def do_GET(self):
"""Serve a GET request."""
# 限制访问的文件为指定的文件
print dir(self.request)
if self.path == "/" + os.path.basename(sys.argv[1]):
f = self.send_head()
if f:
try:
self.copyfile(f, self.wfile)
finally:
f.close()
global TransferCompleted
TransferCompleted = True
print "Complete!"
else:
notify("ERROR", "want to access another file")
def start():
class MyTCPserver(SocketServer.TCPServer):
# seconds
timeout = TIMEOUT
def handle_timeout(self):
"""Called if no new request arrives within self.timeout.
"""
print "Time out!"
# self.shutdown()
notify("TimeOut!", "")
rmQRcode(filename)
sys.exit(0)
httpd = MyTCPserver(("", PORT), MyHandler)
# print "serving at port", PORT
# 文件网址
NetAddr = "http://{}:{}/{}".format(getLocalIP(), PORT, os.path.basename(sys.argv[1]))
print NetAddr
# 二维码文件路径
filename = os.path.join(os.path.join(os.path.expanduser('~')), 'Desktop', randomFileName(5) + ".png")
# 生成并展示二维码
displayQRcode(NetAddr, filename)
# httpd.serve_forever()
# 处理文件下载请求
while not TransferCompleted:
print "Waiting request..."
httpd.handle_request()
# 删除二维码
notify("Transfer completed!", "")
rmQRcode(filename)
if __name__ == '__main__':
# 将python工作目录切换至需要传输的文件所在目录
# 在 macOS 的 Automator 中运行时,工作目录为当前用户~目录
os.chdir(os.path.dirname(sys.argv[1]))
# 在 macOS 的 Automator 中运行时,sys.argv 会是 ['-c','file1', 'file1'],很奇怪
# 理论上, sys.argv 中应该只有两个元素
if len(sys.argv) >= 2 and os.path.isfile(sys.argv[1]):
while True:
try:
start()
except socket.error, e:
# 如果端口被占用,则端口+1再试
if e.errno == 48:
PORT += 1
else:
print "No Error!"
break
else:
notify("错误", "请选择一个文件!")
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment