python上传工具实现
用python模拟浏览器上传文件。
server端的程序:
1 <?php 2 $upload_file = "***".$_FILES['userfile']['name']; 3 if (is_uploaded_file($_FILES['userfile']['tmp_name'])) 4 { 5 if(!move_uploaded_file($_FILES['userfile']['tmp_name'],$upload_file)) 6 { 7 echo "fail"; 8 }else{ 9 echo "success"; 10 echo $_FILES["userfile"]["name"]; 11 } 12 }else 13 { 14 echo "fail"; 15 } 16 echo "\n"; 17 var_dump($_REQUEST); 18 var_dump($_FILES); 19 ?>
客户端程序:
模拟rfc1867给服务器发包:
1 ''' 2 @note: rfc1867 3 ''' 4 import httplib 5 import os 6 import time 7 import mimetypes 8 9 host = "***" 10 selector = "/***/upload.php" 11 12 def get_packet_head(file_name, boundary): 13 def get_boundary(boundary): 14 return "--%s" % boundary 15 def get_file_type(file_name): 16 return mimetypes.guess_type(file_name)[0] or 'application/octet-stream' 17 18 head = [] 19 head.append(get_boundary(boundary)) 20 head.append('Content-Disposition: form-data; name="userfile"; filename="%s"' % file_name) 21 head.append("Content-Type: %s" % get_file_type(file_name)) 22 head.append("") 23 head.append("") 24 return "\r\n".join(head) 25 26 def get_packet_tail(boundary): 27 def get_boundary_end(boundary): 28 return "--%s--" % boundary 29 tail = [] 30 tail.append("") 31 tail.append(get_boundary_end(boundary)) 32 return "\r\n".join(tail) 33 34 def send_packet(file_path): 35 boundary = int(time.time() * 100) 36 file_name = os.path.basename(file_path) 37 38 packet_head = get_packet_head(file_name, boundary) 39 packet_tail = get_packet_tail(boundary) 40 content_length = len(packet_head) + len(packet_tail) + os.path.getsize(file_path) 41 http_conn = httplib.HTTPConnection(host) 42 http_conn.putrequest("POST", selector) 43 http_conn.putheader("Content-Length", str(content_length)) 44 http_conn.putheader("Content-Type", "multipart/form-data; boundary=%s" % boundary) 45 http_conn.endheaders() 46 http_conn.send(packet_head) 47 fp = open(file_path, "rb") 48 chunk_size = 1024 49 while True: 50 data = fp.read(chunk_size) 51 if not data: 52 break 53 http_conn.send(data) 54 http_conn.send(packet_tail) 55 print http_conn.getresponse().read() 56 57 send_packet("tmp.txt")
个人觉得这个协议很坑,居然有boundary这种看起来这么随意的东西存在。
顺便说一下,编码过程中被自己挖的坑坑的很惨,事情是这样的:过程中手贱修改了Content-Disposition中的name字段,然后又大脑短路没有同步服务器端代码,导致怎么执行都echo "fail"。
当时真是有种吃了xx的感觉。抓包看内容,发现前后两次的包的大小不太一样,然后就发现name字段的诡异,后知后觉的我,到这个时候还没有发现问题所在,随手将name改回了"userfile",everything works ok!!!
擦擦,我天真的以为这个字段不能用"_",navie! 直到我瞥了一眼服务器代码里面的$_FILES['userfile'],摔!!!!好吧,自作孽不可活。。。
顺便说一句,The Girl with the Dragon Tattoo 真心不错。
再顺便说一句,今年可能要过双十一了,so kurushiiiiiiiiiii....


浙公网安备 33010602011771号