2016-09-30 19 views
1

SimpleHTTPServerのdo_POSTメソッドを使用してファイルを受信して​​います。スクリプトはcurlを使用してpngファイルをアップロードするとうまくいきますが、ファイルをアップロードするためにPythonリクエストライブラリを使用するたびに、ファイルはアップロードされますが破損します。ここでSimpleHTTPServerコードはファイルをアップロードするためのクライアント側のコードはここにファイルを受け取るPython SimpleHTTPServer

ある

#!/usr/bin/env python 
# Simple HTTP Server With Upload. 

import os 
import posixpath 
import BaseHTTPServer 
import urllib 
import cgi 
import shutil 
import mimetypes 
import re 
try: 
    from cStringIO import StringIO 
except ImportError: 
    from StringIO import StringIO 

class SimpleHTTPRequestHandler(BaseHTTPServer.BaseHTTPRequestHandler):  
    # Simple HTTP request handler with POST commands. 

    def do_POST(self): 
     """Serve a POST request.""" 
     r, info = self.deal_post_data() 
     print r, info, "by: ", self.client_address 
     f = StringIO() 

     if r: 
      f.write("<strong>Success:</strong>") 
     else: 
      f.write("<strong>Failed:</strong>") 

     length = f.tell() 
     f.seek(0) 
     self.send_response(200) 
     self.send_header("Content-type", "text/html") 
     self.send_header("Content-Length", str(length)) 
     self.end_headers() 
     if f: 
      self.copyfile(f, self.wfile) 
      f.close() 

    def deal_post_data(self): 
     print self.headers 
     boundary = self.headers.plisttext.split("=")[1] 
     print 'Boundary %s' %boundary 
     remainbytes = int(self.headers['content-length']) 
     print "Remain Bytes %s" %remainbytes 
     line = self.rfile.readline() 
     remainbytes -= len(line) 
     if not boundary in line: 
      return (False, "Content NOT begin with boundary") 
     line = self.rfile.readline() 
     remainbytes -= len(line) 
     fn = re.findall(r'Content-Disposition.*name="file"; filename="(.*)"', line) 
     if not fn: 
      return (False, "Can't find out file name...") 
     path = self.translate_path(self.path) 
     fn = os.path.join(path, fn[0]) 
     line = self.rfile.readline() 
     remainbytes -= len(line) 
     line = self.rfile.readline() 
     remainbytes -= len(line) 
     try: 
      out = open(fn, 'wb') 
     except IOError: 
      return (False, "Can't create file to write, do you have permission to write?") 

     preline = self.rfile.readline() 
     remainbytes -= len(preline) 
     while remainbytes > 0: 
      line = self.rfile.readline() 
      remainbytes -= len(line) 
      if boundary in line: 
       preline = preline[0:-1] 
       if preline.endswith('\r'): 
        preline = preline[0:-1] 
       out.write(preline) 
       out.close() 
       return (True, "File '%s' upload success!" % fn) 
      else: 
       out.write(preline) 
       preline = line 
     return (False, "Unexpect Ends of data.") 



    def translate_path(self, path): 
     """Translate a /-separated PATH to the local filename syntax. 

     Components that mean special things to the local file system 
     (e.g. drive or directory names) are ignored. (XXX They should 
     probably be diagnosed.) 

     """ 
     # abandon query parameters 
     path = path.split('?',1)[0] 
     path = path.split('#',1)[0] 
     path = posixpath.normpath(urllib.unquote(path)) 
     words = path.split('/') 
     words = filter(None, words) 
     path = os.getcwd() 
     for word in words: 
      drive, word = os.path.splitdrive(word) 
      head, word = os.path.split(word) 
      if word in (os.curdir, os.pardir): continue 
      path = os.path.join(path, word) 
     return path 

    def copyfile(self, source, outputfile): 
     """Copy all data between two file objects. 

     The SOURCE argument is a file object open for reading 
     (or anything with a read() method) and the DESTINATION 
     argument is a file object open for writing (or 
     anything with a write() method). 

     The only reason for overriding this would be to change 
     the block size or perhaps to replace newlines by CRLF 
     -- note however that this the default server uses this 
     to copy binary data as well. 

     """ 
     shutil.copyfileobj(source, outputfile) 



def test(HandlerClass = SimpleHTTPRequestHandler, 
     ServerClass = BaseHTTPServer.HTTPServer): 
    BaseHTTPServer.test(HandlerClass, ServerClass) 

if __name__ == '__main__': 
    test() 

ある

#!/usr/bin/python 

import requests 

files = {'file': open('test.png', 'rb')} 
r = requests.post('http://192.168.5.134:8000', files=files) 
print r.request.headers 

ファイルアップロードに成功したが破損しました。カール使用

python request header

SimpleHTTPServer response

[カール-F '[email protected]' を192.168.5.134:8000/ -v]、ファイルアップロードし、正常に開かれました。

python-request codeに問題はありますか?

答えて

2

curlrequestは少し異なるヘッダーを持っていますが、curlには空の行があり、requestsはありません。

次のブロック

if line.strip(): 
    preline = line 
else: 
    preline = self.rfile.readline() 
+0

アメージングでpreline = self.rfile.readline()を交換してください! :)ありがとうございました、サー@マクシミラン – john

関連する問題