diff --git a/rhodecode/controllers/files.py b/rhodecode/controllers/files.py --- a/rhodecode/controllers/files.py +++ b/rhodecode/controllers/files.py @@ -361,26 +361,26 @@ class FilesController(BaseRepoController except (ImproperArchiveTypeError, KeyError): return _('Unknown archive type') - fd, _archive_name = tempfile.mkstemp(suffix='rcarchive') - with open(_archive_name, 'wb') as f: - cs.fill_archive(stream=f, kind=fileformat, subrepos=subrepos) - - content_disposition = 'attachment; filename=%s-%s%s' \ - % (repo_name, revision[:12], ext) - content_length = os.path.getsize(_archive_name) + fd, archive = tempfile.mkstemp() + t = open(archive, 'wb') + cs.fill_archive(stream=t, kind=fileformat, subrepos=subrepos) + t.close() - headers = [('Content-Disposition', str(content_disposition)), - ('Content-Type', str(content_type)), - ('Content-Length', str(content_length))] + def get_chunked_archive(archive): + stream = open(archive, 'rb') + while True: + data = stream.read(16 * 1024) + if not data: + stream.close() + os.close(fd) + os.remove(archive) + break + yield data - class _DestroyingFileWrapper(_FileIter): - def close(self): - self.file.close - os.remove(self.file.name) - - request.environ['wsgi.file_wrapper'] = _DestroyingFileWrapper - fapp = FileApp(_archive_name, headers=headers) - return fapp(request.environ, self.start_response) + response.content_disposition = str('attachment; filename=%s-%s%s' \ + % (repo_name, revision[:12], ext)) + response.content_type = str(content_type) + return get_chunked_archive(archive) @HasRepoPermissionAnyDecorator('repository.read', 'repository.write', 'repository.admin') diff --git a/rhodecode/tests/functional/test_files.py b/rhodecode/tests/functional/test_files.py --- a/rhodecode/tests/functional/test_files.py +++ b/rhodecode/tests/functional/test_files.py @@ -200,9 +200,10 @@ class TestFilesController(TestController self.assertEqual(response.status, '200 OK') heads = [ - ('Content-Type', 'text/html; charset=utf-8'), - ('Content-Length', '0'), ('Pragma', 'no-cache'), - ('Cache-Control', 'no-cache') + ('Pragma', 'no-cache'), + ('Cache-Control', 'no-cache'), + ('Content-Disposition', 'attachment; filename=%s' % filename), + ('Content-Type', '%s; charset=utf-8' % info[0]), ] self.assertEqual(response.response._headers.items(), heads) @@ -212,7 +213,8 @@ class TestFilesController(TestController for arch_ext in ['tar', 'rar', 'x', '..ax', '.zipz']: fname = '27cd5cce30c96924232dffcd24178a07ffeb5dfc%s' % arch_ext - response = self.app.get(url(controller='files', action='archivefile', + response = self.app.get(url(controller='files', + action='archivefile', repo_name=HG_REPO, fname=fname)) response.mustcontain('Unknown archive type') @@ -220,10 +222,11 @@ class TestFilesController(TestController def test_archival_wrong_revision(self): self.log_user() - for rev in ['00x000000', 'tar', 'wrong', '@##$@$424213232', '232dffcd']: + for rev in ['00x000000', 'tar', 'wrong', '@##$@$42413232', '232dffcd']: fname = '%s.zip' % rev - response = self.app.get(url(controller='files', action='archivefile', + response = self.app.get(url(controller='files', + action='archivefile', repo_name=HG_REPO, fname=fname)) response.mustcontain('Unknown revision')