python CGI : upload error
Question: I use Python version 3.4

and this is server source code in python

    
    
    import io
    from socket import *
    import threading
    import cgi
    
    serverPort = 8181
    serverSocket = socket(AF_INET, SOCK_STREAM)
    serverSocket.bind(('', serverPort))
    serverSocket.listen(5)
    
    
    def serverHandle(connectionSocket, addr):     
        try:
            message = connectionSocket.recv(1024)
    
            if not message:
                return
    
            path = message.split()[1].decode('utf-8')
    
            if path == '/':
                connectionSocket.send(b'HTTP/1.1 200 OK\r\n')
                connectionSocket.send(b'Content-type: text/html\r\n\r\n')
                with open('upload.html', 'rb') as f:
                    connectionSocket.send(f.read())
    
            elif path == '/upload':
                header = message.split(b'\r\n\r\n')[0]
                query = message.split(b'\r\n\r\n')[-1]
    
                if not query:
                    return
    
                fp = io.BytesIO(query)
    
                form = cgi.FieldStorage(fp, environ={'REQUEST_METHOD':'POST', 'CONTENT_TYPE': 'multipart/form-data'})
    
                f = open(form.filename, 'w')
                f.write(form.file)
                f.close()
    
            connectionSocket.close()
    
        except IOError:
            connectionSocket.send('404 File Not Found\r\n\r\n'.encode('utf_8'))
            connectionSocket.close()
    
    while True:
        connectionSocket, addr = serverSocket.accept();
        threading._start_new_thread(serverHandle, (connectionSocket, addr))
    serverSocket.close()
    

and upload HTML source is here

    
    
    <HTML>
        <BODY>
            <FORM ENCTYPE="multipart/form-data" ACTION="http://127.0.0.1:8181/upload" METHOD=POST>
            File to process: <INPUT NAME="file" TYPE="file">
            <INPUT TYPE="submit" VALUE="Send File">
            </FORM>
        </BODY>
    </HTML>
    

I try upload file to server and save file in directory but error is occurred
like this

    
    
    Unhandled exception in thread started by <function serverHandle at 0x000000000240CBF8>
    Traceback (most recent call last):
      File "C:\Users\Inwoo\Eclipse\workspace\WebServer\src\webserver1.py", line 36, in serverHandle
        form = cgi.FieldStorage(fp, environ={'REQUEST_METHOD':'POST', 'CONTENT_TYPE': 'multipart/form-data'})
      File "C:\Python34\lib\cgi.py", line 559, in __init__
        self.read_multi(environ, keep_blank_values, strict_parsing)
      File "C:\Python34\lib\cgi.py", line 681, in read_multi
        raise ValueError('Invalid boundary in multipart form: %r' % (ib,))
    ValueError: Invalid boundary in multipart form: b''
    

I cant understand this problem?

and sometimes query of message is empty!

so I wrote `if not query: return`, is it correct?

and how can I receive uploaded file and save them in server?


Answer: You need to _not_ split the query on as many newlines as you do; there can be
embedded newlines in it. Use `str.partition()` instead here:

    
    
    header, _, query = message.partition(b'\r\n\r\n')
    

You'll have to parse the headers; the `Content-Type` header contains the
multipart boundary; the `FieldStorage` instance needs this to determine where
the fields begin and end.

    
    
    import re
    
    content_type = re.search(br'content-type:\s+(.*?)\r\n', header, flags=re.I).group(1)
    
    form = cgi.FieldStorage(fp, environ={'REQUEST_METHOD':'POST', 'CONTENT_TYPE': content_type})
    

Take into account that a HTTP message with a file upload can easily contain
much more that 1024 bytes; you only ever read that little. _Just the headers_
can easily make up most of the message; my browser sends 819 bytes for the
header and keeps that in one packet. Your `connectionSocket.recv(1024)` call
will then contain **just those headers** and you'll need to read more data
still.

