def upload(request): """View used when support for Nginx Upload Progress module has been disabled. This view includes 3 steps: 1. We change the "state" column in the upload table so that our AJAX-called 'progress' view sees that the upload has started and that the temporary file can be stat'ed. 2. We copy the data from the POST request to a temporary file. This step is long, obviously, as we copy data as we receive it from the browser. While we are copying data, the browser will call the 'progress' view to update a progress bar. 3. Once the file has been copied, we rename it to its final filename and redirect the browser to the success page. """ # We pass the 'file_id' in the query string as a GET parameter. If # we read it from the POSTed data, WebOb would read all POSTed # data, which has various features and traps (like setting the # "Content-Length" header to 0) that we do not need since we are # going to read the data ourselves anyway. file_id = request.GET['X-Progress-ID'] input_file, file_size, filename = get_file_from_request(request) session = DBSession() u = session.query(Upload).filter_by(id=file_id).one() upload_dir = request.registry.settings['poulda.upload_dir'] user_id = authenticated_userid(request) # We use a temporary path to detect unfinished uploads (post # mortem, not in the application itself). path = os.path.join(upload_dir, '_'.join((user_id, file_id))) u.tmp_path = path u.started = int(time.time()) u.size = file_size u.state = u'uploading' session.flush() # We need to commit the transaction so that changes to the Upload # object can be seen by the other threads (which will serve the # 'progress' JSON view called by the upload page). transaction.commit() with open(path, 'w') as output: # We must read only 'file_size' bytes from the 'input_file', # not all of it since it also contains the MIME boundary. copy_to_file(input_file, file_size, output) final_path = filename[1 + filename.rfind(os.sep):] final_path = os.path.join(upload_dir, final_path) os.rename(path, final_path) session = DBSession() u = session.query(Upload).filter_by(id=file_id).one() u.state = u'done' u.final_path = unicode(final_path, 'utf-8') return HTTPFound(location='success')
def upload_with_nginx_upload_progress(request): """View used when Nginx Upload Progress module is enabled. When the Nginx Upload Progress module is used, we get to the WSGI application (and thus to this view) only when the file has been completely written to disk by Nginx. So here we merely copy it to the final upload directory and that is all. """ input_file, file_size, filename = get_file_from_request(request) upload_dir = request.registry.settings['poulda.upload_dir'] path = os.path.join(upload_dir, filename) with open(path, 'w') as output: # We must read only 'file_size' bytes from the 'input_file', # not all of it since it also contains the MIME boundary. copy_to_file(input_file, file_size, output) return HTTPFound(location='success')
def call_fut(self, *args, **kwargs): from poulda.utils import copy_to_file return copy_to_file(*args, **kwargs)