python 2.7 simple file upload

Development environment

wsgi, ckan, python2.7, jquery1.4 use

An error occurred during development of python cgi simple file upload. Ajax upload request Chrome Debugging shows the file fine. It is also included in wsgi.input in the server log environ. Take that data out and make it into a tempfile Is it not properly created to create FieldStorage? All values ​​in FieldStorage are empty

HTML

<input type="file" name="add_code_linkfileup" style="display: none;">

Script

    input_file.onchange = function(){
       pop_file_upload("INPUT[name ="+event.target.name+"]");
    };
    
    function pop_file_upload(target){
        var form_data = new FormData();
        form_data.id = "form";
        form_data.enctype = 'multipart/form-data';
        form_data.append('file', $(target).prop('files')[0]);
        $.ajax({
            type: 'POST',
            url:  '/api/3/custom/pop_file_upload',
            dataType:'json',
            data: form_data,
            enctype: 'multipart/form-data',
            contentType: false,
            cache: false,
            processData: false,
            success: function(data) {
                console.log('Success!');
            },
            beforeSend:function(){
                console.log("file upload start");
            },
            complete:function(){
                $(target).val('');
                console.log("file upload end");
            }
       });
    }

chrome debug network

    Form Data
    ------WebKitFormBoundaryH3daMRABWxXq3BDS
    Content-Disposition: form-data; name="file"; filename="industry.jpg"
    Content-Type: image/jpeg
    
    
    ------WebKitFormBoundaryH3daMRABWxXq3BDS--
    

python source

    def read_body(self, environ):
        stream = environ['wsgi.input']
        length = int(environ.get('CONTENT_LENGTH', 0))
        log.debug("read_body=================%s" % length)
        body = TemporaryFile(mode='w+b')
        while length > 0:
            part = stream.read(min(length, 1024 * 200))  # 200KB buffer size
            if not part: break
            body.write(part)
            length -= len(part)
        body.seek(0)
        environ['wsgi.input'] = body
        return body

    def pop_file_upload(self, environ, start_response):
        body = self.read_body(environ)
        log.debug("pop_file_upload=================%s" % body)
    
        filefield = cgi.FieldStorage(environ=environ, fp=body, keep_blank_values=1)
        log.debug("pop_file_upload=================%s" % filefield)
        if isinstance(filefield, list):
            # Multiple files uploaded
            log.debug('<p>Check uploaded multiple images: </p>')
            for fileitem in filefield:
                fn = os.path.basename(fileitem.filename)
                log.debug("file_name===%s"% fn)
                with open("upload/{}".format(fn), 'wb') as f:
                    f.write(fileitem.file.read())
                log.debug('<img width="200" height="auto" src="upload/{}" /><br><br>'.format(fn))
        else:
            # Single file uploaded
            log.debug('<p>Check uploaded image: </p>')
            fn = os.path.basename(filefield['file'].filename)
            log.debug("file_name===%s" % fn)
            with open("upload/{}".format(fn), 'wb') as f:
                f.write(filefield.file.read())
            log.debug('<img width="200" height="auto" src="upload/{}" />'.format(fn))

environ

    'wsgi.input': <FakeCGIBody at 0x7f798f891610 viewing MultiDict([('fi...'))])>, 

error

    1. `length = int(environ.get('CONTENT_LENGTH', 0))` allways zero..
       * `environ.get('CONTENT_LENGTH', 0)` Notfound..return zero
    2. `pop_file_upload=================FieldStorage(None, None, [])` <- empty
    3. `fn = os.path.basename(filefield['file'].filename)` <- KeyError

help

Why can't I access the file information?

Is there anything I missed?

please give me a hint

Answer

The communication methods of ckan, wsgi, and python were not known exactly. However, only CGI body data came into “environ” and “FieldStorage” was not created normally when “wsgi.input” was created using that data. The reason is that it was already in the form of file storage. However, “wsgi.input” is a cgi object and cannot be read as a read. The final solution was processed by reading the data of “webob._parseed_post_vars”