SebaGeek Quod erat expectandum.

Scripte & Zeug: Python Sendfile Script

Das ist ein kleines Script, welches ich gebastelt hab um schnell mal ein paar Dateien im LAN zu verschicken. Startet man das Script, so öffnet es einen threaded Webserver auf Port 8080 und erlaubt es anderen diese Datei über Http herunterzuladen (der angegebene Pfad wird dabei ignoriert).

In v0.2 kommt nun auch wget prima mit den Downloaden klar. Wget hat den HTTP-Header-Attachment foo nicht interpretiert, aber wenn man einfach einen 302 auf die Datei macht, dann ist das ja alles kein Problem. Ausserdem wird nun auch angezeigt, wenn ein Client mit dem Downloaden fertig ist oder er ihn abgebrochen hat.

Download sendfile.py (2.6 kb)
 1 #!/usr/bin/python
 2 # -*- coding: utf-8 -*-
 3 
 4 # written by seba (seba-geek.de) :)
 5 # v0.2
 6 
 7 import BaseHTTPServer
 8 import sys
 9 import os
10 import urllib
11 from stat import ST_SIZE
12 import SocketServer
13 import socket
14 import commands
15 
16 class FileHandler(BaseHTTPServer.BaseHTTPRequestHandler):
17 	fileName = "Undefined"
18 	filePath = "/dev/null"
19 	fileLength = 0
20 	blockSize = 1024 * 1024
21 	
22 	def do_GET(self):
23 		if urllib.unquote(self.path) != "/" + self.fileName:
24 			self.send_response(302)
25 			self.send_header('Location', '/' + self.fileName)
26 			self.end_headers()
27 			return
28 		self.send_response(200)
29 		self.send_header('Content-Disposition', 'attachment; filename="%s"' % self.fileName)
30 		self.send_header('Content-type', 'application/octet-stream')
31 		self.send_header('Content-Transfer-Encoding', ' binary')
32 		self.send_header('Content-Length', self.fileLength)
33 		self.end_headers()
34 		myfile = open(self.filePath, 'rb')
35 		block = myfile.read(self.blockSize)
36 		while block:
37 			try:
38 				self.wfile.write(block)
39 			except socket.error,e:
40 				print "%s ABORTED transmission (Reason %s: %s)" % (self.client_address[0], e[0], e[1])
41 				return
42 			block = myfile.read(self.blockSize)
43 		myfile.close()
44 		print "%s finished downloading" % (self.client_address[0])
45 		return
46 
47 class ThreadedHTTPServer(SocketServer.ThreadingMixIn, BaseHTTPServer.HTTPServer):
48 	pass
49 
50 def main():
51 	if len(sys.argv) < 2 or len(sys.argv) > 3 or sys.argv[1] in ('-h', '--help'):
52 		print "Usage: [path to file] <port=8080>"
53 		return
54 	
55 	port = 8080
56 	if len(sys.argv) == 3:
57 		try:
58 			port = int(sys.argv[2])
59 		except ValueError:
60 			print "Error: Port should be an int!"
61 			return
62 	
63 	try:
64 		testit = open(sys.argv[1], 'r')
65 		testit.close()
66 		FileHandler.filePath = sys.argv[1]
67 		FileHandler.fileName = os.path.basename(sys.argv[1])
68 		FileHandler.fileLength = os.stat(sys.argv[1])[ST_SIZE]
69 	except IOError:
70 		print "Error: Could not open file!"
71 		return
72 	
73 	server = ThreadedHTTPServer(('', port), FileHandler)
74 	print "Serving:", sys.argv[1]
75 	print "Port: ", port
76 	print "Ready..."
77 	server.address_family = 10
78 	# print urls with local network adresses
79 	print "Some addresses this file will be available under:"
80 	ips = commands.getoutput(r"/sbin/ifconfig |grep 'inet6\?'|grep -v 127.0.0.1|grep -v ' fe80'|grep -v ::1|sed -n 's/.*inet6\?[a-zA-Z: -]\+\([0-9a-fA-F.:]*\).*/\1/p'")
81 	for ip in ips.split("\n"):
82 		if ip.find(":") >= 0:
83 			ip = "[%s]" % ip # must be v6...
84 			continue	# FIXME: When BaseHTTP supports ipv6 properly, delete this line
85 		print "http://%s:%d" % (ip, port)
86 	
87 	try:
88 		server.serve_forever()
89 	except KeyboardInterrupt:
90 		server.socket.close()
91 	print "Good bye.."
92 
93 if __name__ == '__main__':
94 	main()
π