Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
branch: master
Fetching contributors…

Cannot retrieve contributors at this time

file 78 lines (57 sloc) 2.882 kb

File Uploads

There are two parts necessary for handling file uploads. The first is to make sure you have a form that's been setup correctly to accept files. This means adding enctype attribute to your form element with the value of multipart/form-data. A very simple example would be a form that accepts an mp3 file. Notice we've setup the form as previously explained and also added an input element of the file type.

The second part is handling the file upload in your view callable (above, assumed to answer on /store_mp3_view). The uploaded file is added to the request object as a cgi.FieldStorage object accessible through the request.POST multidict. The two properties we're interested in are the file and filename and we'll use those to write the file to disk:

import os
import uuid
from pyramid.response import Response

def store_mp3_view(request):
    # ``filename`` contains the name of the file in string format.
    #
    # WARNING: this example does not deal with the fact that IE sends an
    # absolute file *path* as the filename.  This example is naive; it
    # trusts user input.

    filename = request.POST['mp3'].filename

    # ``input_file`` contains the actual file data which needs to be
    # stored somewhere.

    input_file = request.POST['mp3'].file

    # Note that we are generating our own filename instead of trusting
    # the incoming filename since that might result in insecure paths.
    # Please note that in a real application you would not use /tmp,
    # and if you write to an untrusted location you will need to do
    # some extra work to prevent symlink attacks.

    file_path = os.path.join('/tmp', '%s.mp3' % uuid.uuid4())

    # We first write to a temporary file to prevent incomplete files from
    # being used.

    temp_file_path = file_path + '~'
    output_file = open(temp_file_path, 'wb')

    # Finally write the data to a temporary file
    input_file.seek(0)
    while True:
        data = input_file.read(2<<16)
        if not data:
            break
        output_file.write(data)

    # If your data is really critical you may want to force it to disk first
    # using output_file.flush(); os.fsync(output_file.fileno())

    output_file.close()

    # Now that we know the file has been fully saved to disk move it into place.

    os.rename(temp_file_path, file_path)

    return Response('OK')
Something went wrong with that request. Please try again.