python CGI : upload error

2019-08-14 17:28发布

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?

1条回答
倾城 Initia
2楼-- · 2019-08-14 18:09

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.

查看更多
登录 后发表回答