def setContentHeaders(self, file, offset, endByte, contentDisposition=None): """ Sets the Content-Length, Content-Disposition, Content-Type, and also the Content-Range header if this is a partial download. :param file: The file being downloaded. :param offset: The start byte of the download. :type offset: int :param endByte: The end byte of the download (non-inclusive). :type endByte: int :param contentDisposition: Content-Disposition response header disposition-type value, if None, Content-Disposition will be set to 'attachment; filename=$filename'. :type contentDisposition: str or None """ setResponseHeader( 'Content-Type', file.get('mimeType') or 'application/octet-stream') setContentDisposition(file['name'], contentDisposition or 'attachment') setResponseHeader('Content-Length', max(endByte - offset, 0)) if (offset or endByte < file['size']) and file['size']: setResponseHeader( 'Content-Range', 'bytes %d-%d/%d' % (offset, endByte - 1, file['size']))
def setContentHeaders(self, file, offset, endByte, contentDisposition=None): """ Sets the Content-Length, Content-Disposition, Content-Type, and also the Content-Range header if this is a partial download. :param file: The file being downloaded. :param offset: The start byte of the download. :type offset: int :param endByte: The end byte of the download (non-inclusive). :type endByte: int :param contentDisposition: Content-Disposition response header disposition-type value, if None, Content-Disposition will be set to 'attachment; filename=$filename'. :type contentDisposition: str or None """ isRangeRequest = cherrypy.request.headers.get('Range') setResponseHeader('Content-Type', file.get('mimeType') or 'application/octet-stream') setContentDisposition(file['name'], contentDisposition or 'attachment') setResponseHeader('Content-Length', max(endByte - offset, 0)) if (offset or endByte < file['size'] or isRangeRequest) and file['size']: setResponseHeader( 'Content-Range', 'bytes %d-%d/%d' % (offset, endByte - 1, file['size']))
def pathDownload(self, path): user = self.getCurrentUser() path = '/'.join(path) resource = path_util.lookUpPath(path, user)['document'] if resource['_modelType'] == 'file': singleFile = resource else: model = self._getResourceModel(resource['_modelType'], 'fileList') singleFile = None for _path, file in model.fileList(doc=resource, user=user, subpath=True, data=False): if singleFile is None: singleFile = file else: singleFile = False break if singleFile is not False and singleFile is not None: offset, endByte = 0, None rangeHeader = cherrypy.lib.httputil.get_ranges( cherrypy.request.headers.get('Range'), singleFile.get('size', 0)) if rangeHeader and len(rangeHeader): offset, endByte = rangeHeader[0] singleFile = File().load(singleFile['_id'], user=user, level=AccessType.READ) return File().download(singleFile, offset, endByte=endByte) setResponseHeader('Content-Type', 'application/zip') setContentDisposition(resource.get('name', 'Resources') + '.zip') def stream(): zip = ziputil.ZipGenerator() for (path, file) in model.fileList( doc=resource, user=user, subpath=True): for data in zip.addFile(file, path): yield data yield zip.footer() return stream
def _set_content_disposition(self, name, content_disposition, mime_type=None): setResponseHeader('Content-Type', mime_type or 'application/octet-stream') setContentDisposition(name, content_disposition or 'attachment')
def download(self, assign_id, image_name): assignment = self.folder_m.load(assign_id, user=self.getCurrentUser(), level=AccessType.READ) label_folder = find_folder(p_folder=assignment, name=image_name, user=self.getCurrentUser(), create=True) folder = find_folder(p_folder=label_folder, name=self.label_image_folder_name, user=self.getCurrentUser(), create=True) printOk(folder) setResponseHeader('Content-Type', 'application/zip') setContentDisposition(label_folder['name'] + '.zip') user = self.getCurrentUser() def stream(): zip = ziputil.ZipGenerator(folder['name']) for (path, file) in self.folder_m.fileList(folder, user=user, subpath=False): for data in zip.addFile(file, path): yield data yield zip.footer() return stream
def exportTale(self, tale, params): user = self.getCurrentUser() folder = self.model('folder').load(tale['folderId'], user=user, level=AccessType.READ, exc=True) image = self.model('image', 'wholetale').load(tale['imageId'], user=user, level=AccessType.READ, exc=True) recipe = self.model('recipe', 'wholetale').load(image['recipeId'], user=user, level=AccessType.READ, exc=True) # Construct a sanitized name for the ZIP archive using a whitelist # approach zip_name = re.sub('[^a-zA-Z0-9-]', '_', tale['title']) setResponseHeader('Content-Type', 'application/zip') setContentDisposition(zip_name + '.zip') # Temporary: Fetch the GitHub archive of the recipe. Note that this is # done in a streaming fashion because ziputil makes use of generators # when files are added to the zip url = '{}/archive/{}.tar.gz'.format(recipe['url'], recipe['commitId']) req = requests.get(url, stream=True) def stream(): zip = ziputil.ZipGenerator(zip_name) # Add files from the Tale folder for (path, f) in self.model('folder').fileList(folder, user=user, subpath=False): for data in zip.addFile(f, path): yield data # Temporary: Add Image metadata for data in zip.addFile(lambda: image.__str__(), 'image.txt'): yield data # Temporary: Add Recipe metadata for data in zip.addFile(lambda: recipe.__str__(), 'recipe.txt'): yield data # Temporary: Add a zip of the recipe archive # TODO: Grab proper filename from header # e.g. 'Content-Disposition': 'attachment; filename= \ # jupyter-base-b45f9a575602e6038b4da6333f2c3e679ee01c58.tar.gz' for data in zip.addFile(req.iter_content, 'archive.tar.gz'): yield data yield zip.footer() return stream
def exportTale(self, tale, taleFormat): user = self.getCurrentUser() zip_name = str(tale['_id']) if taleFormat == 'bagit': exporter = BagTaleExporter(tale, user, expand_folders=True) elif taleFormat == 'native': exporter = NativeTaleExporter(tale, user) setResponseHeader('Content-Type', 'application/zip') setContentDisposition(zip_name + '.zip') return exporter.stream
def download(self, colormap, name): setContentDisposition(name) def stream(): yield json.dumps({ 'colormap': colormap['colormap'] }, sort_keys=True, allow_nan=False, cls=JsonEncoder).encode('utf8') setResponseHeader('Content-Type', 'application/json') return stream
def downloadKeyFile(self, file, algo): self._validateAlgo(algo) if algo not in file: raise RestException('This file does not have the %s hash computed.' % algo) keyFileBody = '%s\n' % file[algo] name = '.'.join((file['name'], algo)) setResponseHeader('Content-Length', len(keyFileBody)) setResponseHeader('Content-Type', 'text/plain') setContentDisposition(name) setRawResponse() return keyFileBody
def downloadKeyFile(self, file, algo): self._validateAlgo(algo) if algo not in file: raise RestException('This file does not have the %s hash computed.' % algo) keyFileBody = '%s\n' % file[algo] name = '.'.join((file['name'], algo)) setResponseHeader('Content-Length', len(keyFileBody)) setResponseHeader('Content-Type', 'text/plain') setContentDisposition(name) setRawResponse() return keyFileBody
def export(self, folder, params): setResponseHeader('Content-Type', 'application/zip') setContentDisposition(folder['name'] + '.zip') def stream(): zip = ziputil.ZipGenerator(folder['name']) for data in zip.addFile(DetectionResource.generateKPFContent(folder), folder['name'] + '.geom.kpf'): yield data for data in zip.addFile(TypesResource.generateKPFContent(folder), folder['name'] + '.types.kpf'): yield data for data in zip.addFile(ActivitiesResource.generateKPFContent(folder), folder['name'] + '.activities.kpf'): yield data yield zip.footer() return stream
def iter(self, fields, files): encoder = codecs.getencoder('utf-8') for (key, value) in fields: key = self.u(key) yield encoder('--%s\r\n' % self.boundary) yield encoder( self.u('Content-Disposition: form-data; ' 'name="%s"\r\n') % key) yield encoder('\r\n') if isinstance(value, int) or isinstance(value, float): value = str(value) yield encoder(self.u(value)) yield encoder('\r\n') for (key, filename, content) in files: key = self.u(key) filename = self.u(filename) yield encoder('--%s\r\n' % self.boundary) disposition = setContentDisposition(filename, 'form-data; name="%s"' % key, False) yield encoder( self.u('Content-Disposition: ') + self.u(disposition)) yield encoder('Content-Type: application/octet-stream\r\n') yield encoder('\r\n') yield (content, len(content)) yield encoder('\r\n') yield encoder('--%s--\r\n' % self.boundary)
def export_all(self, folder, excludeBelowThreshold): _, gen = self._generate_detections(folder, excludeBelowThreshold) setResponseHeader('Content-Type', 'application/zip') setContentDisposition(folder['name'] + '.zip') user = self.getCurrentUser() def stream(): z = ziputil.ZipGenerator(folder['name']) for (path, file) in Folder().fileList(folder, user=user, subpath=False): for data in z.addFile(file, path): yield data for data in z.addFile(gen, "output_tracks.csv"): yield data yield z.footer() return stream
def _getRequestHeaders(self, upload): return { 'Content-Disposition': setContentDisposition(upload['name'], setHeader=False), 'Content-Type': upload.get('mimeType', ''), 'x-amz-acl': 'private', 'x-amz-meta-uploader-id': str(upload['userId']), 'x-amz-meta-uploader-ip': str(cherrypy.request.remote.ip) }
def _getRequestHeaders(self, upload): headers = { 'Content-Disposition': setContentDisposition(upload['name'], setHeader=False), 'Content-Type': upload.get('mimeType', ''), 'x-amz-acl': 'private', 'x-amz-meta-uploader-id': str(upload['userId']), 'x-amz-meta-uploader-ip': str(cherrypy.request.remote.ip) } if self.assetstore.get('serverSideEncryption'): headers['x-amz-server-side-encryption'] = 'AES256' return headers
def _getRequestHeaders(self, upload): headers = { 'Content-Disposition': setContentDisposition(upload['name'], setHeader=False), 'Content-Type': upload.get('mimeType', ''), 'x-amz-acl': 'private', 'x-amz-meta-uploader-id': str(upload['userId']), 'x-amz-meta-uploader-ip': str(cherrypy.request.remote.ip) } if self.assetstore.get('serverSideEncryption'): headers['x-amz-server-side-encryption'] = 'AES256' return headers
def downloadArchiveFile(self, file, path, offset, endByte, contentDisposition, extraParameters): """ Requires read permission on the folder that contains the file's item. """ with ArchiveFileHandle(File(), file, path) as fileobj: info = fileobj.info() rangeHeader = cherrypy.lib.httputil.get_ranges( cherrypy.request.headers.get('Range'), info['size']) # The HTTP Range header takes precedence over query params if rangeHeader and len(rangeHeader): # Currently we only support a single range. offset, endByte = rangeHeader[0] if offset: fileobj.seek(offset) else: offset = 0 if endByte is None or endByte > info['size']: endByte = info['size'] setResponseHeader('Accept-Ranges', 'bytes') setResponseHeader('Content-Type', 'application/octet-stream') setContentDisposition(os.path.basename(path), contentDisposition or 'attachment') setResponseHeader('Content-Length', max(endByte - offset, 0)) if (offset or endByte < file['size']) and file['size']: setResponseHeader( 'Content-Range', 'bytes %d-%d/%d' % (offset, endByte - 1, file['size'])) def downloadGenerator(): pos = offset while pos < endByte: data = fileobj.read(min(65536, endByte - pos)) yield data pos += len(data) if pos >= endByte: break return downloadGenerator
def download_folder(self, event, path, root, user=None): self.is_dir(path, root["_id"]) setResponseHeader("Content-Type", "application/zip") setContentDisposition(path.name + ".zip") def stream(): def recursive_file_list(p): for obj in p.iterdir(): if obj.is_file(): yield obj elif obj.is_dir(): yield from recursive_file_list(obj) zip_stream = ziputil.ZipGenerator(rootPath="") for obj in recursive_file_list(path): zip_path = os.path.relpath(obj.as_posix(), path.as_posix()) for data in zip_stream.addFile(lambda: file_stream(obj), zip_path): yield data yield zip_stream.footer() event.preventDefault().addResponse(stream)
def _getRequestHeaders(self, upload): return { 'Content-Disposition': setContentDisposition(upload['name'], setHeader=False), 'Content-Type': upload.get('mimeType', ''), 'x-amz-acl': 'private', 'x-amz-meta-uploader-id': str(upload['userId']), 'x-amz-meta-uploader-ip': str(cherrypy.request.remote.ip) }
def iter(self, fields, files): encoder = codecs.getencoder('utf-8') for (key, value) in fields: key = self.u(key) yield encoder('--%s\r\n' % self.boundary) yield encoder(self.u('Content-Disposition: form-data; ' 'name="%s"\r\n') % key) yield encoder('\r\n') if isinstance(value, int) or isinstance(value, float): value = str(value) yield encoder(self.u(value)) yield encoder('\r\n') for (key, filename, content) in files: key = self.u(key) filename = self.u(filename) yield encoder('--%s\r\n' % self.boundary) disposition = setContentDisposition(filename, 'form-data; name="%s"' % key, False) yield encoder(self.u('Content-Disposition: ') + self.u(disposition)) yield encoder('Content-Type: application/octet-stream\r\n') yield encoder('\r\n') yield (content, len(content)) yield encoder('\r\n') yield encoder('--%s--\r\n' % self.boundary)
def testSetContentDisposition(name, disp, expected): if disp is None: assert rest.setContentDisposition(name, setHeader=False) == expected else: assert rest.setContentDisposition(name, disp, setHeader=False) == expected
def testSetContentDispositionFails(name, disp, msg): with pytest.raises(rest.RestException, match=msg): rest.setContentDisposition(name, disp, setHeader=False)
def testSetContentDisposition(self): with six.assertRaisesRegex( self, rest.RestException, 'Error: Content-Disposition \(.*\) is not a recognized value.'): rest.setContentDisposition('filename', 'unknown', False) with six.assertRaisesRegex( self, rest.RestException, 'Error: Content-Disposition filename is empty.'): rest.setContentDisposition('', setHeader=False) self.assertEqual(rest.setContentDisposition( 'filename', setHeader=False), 'attachment; filename="filename"') self.assertEqual(rest.setContentDisposition( 'filename', 'inline', setHeader=False), 'inline; filename="filename"') self.assertEqual(rest.setContentDisposition( 'filename', 'form-data; name="chunk"', setHeader=False), 'form-data; name="chunk"; filename="filename"') self.assertEqual(rest.setContentDisposition( 'file "name"', setHeader=False), 'attachment; filename="file \\"name\\""') self.assertEqual(rest.setContentDisposition( 'file\\name', setHeader=False), 'attachment; filename="file\\\\name"') self.assertEqual(rest.setContentDisposition( u'\u043e\u0431\u0440\u0430\u0437\u0435\u0446', setHeader=False), 'attachment; filename=""; filename*=UTF-8\'\'' '%D0%BE%D0%B1%D1%80%D0%B0%D0%B7%D0%B5%D1%86') self.assertEqual(rest.setContentDisposition( u'\U0001f603', setHeader=False), 'attachment; filename=""; filename*=UTF-8\'\'%F0%9F%98%83')
def export_detections(self, folder, excludeBelowThreshold): filename, gen = self._generate_detections(folder, excludeBelowThreshold) setContentDisposition(filename) return gen
def testSetContentDisposition(name, disp, expected): if disp is None: assert rest.setContentDisposition(name, setHeader=False) == expected else: assert rest.setContentDisposition(name, disp, setHeader=False) == expected
def testSetContentDisposition(self): with six.assertRaisesRegex( self, rest.RestException, 'Error: Content-Disposition \(.*\) is not a recognized value.' ): rest.setContentDisposition('filename', 'unknown', False) with six.assertRaisesRegex( self, rest.RestException, 'Error: Content-Disposition filename is empty.'): rest.setContentDisposition('', setHeader=False) self.assertEqual( rest.setContentDisposition('filename', setHeader=False), 'attachment; filename="filename"') self.assertEqual( rest.setContentDisposition('filename', 'inline', setHeader=False), 'inline; filename="filename"') self.assertEqual( rest.setContentDisposition('filename', 'form-data; name="chunk"', setHeader=False), 'form-data; name="chunk"; filename="filename"') self.assertEqual( rest.setContentDisposition('file "name"', setHeader=False), 'attachment; filename="file \\"name\\""') self.assertEqual( rest.setContentDisposition('file\\name', setHeader=False), 'attachment; filename="file\\\\name"') self.assertEqual( rest.setContentDisposition( u'\u043e\u0431\u0440\u0430\u0437\u0435\u0446', setHeader=False), 'attachment; filename=""; filename*=UTF-8\'\'' '%D0%BE%D0%B1%D1%80%D0%B0%D0%B7%D0%B5%D1%86') self.assertEqual( rest.setContentDisposition(u'\U0001f603', setHeader=False), 'attachment; filename=""; filename*=UTF-8\'\'%F0%9F%98%83')
def testSetContentDispositionFails(name, disp, msg): with pytest.raises(rest.RestException, match=msg): rest.setContentDisposition(name, disp, setHeader=False)
def csvExportDownload(self, params): setResponseHeader('Content-Type', 'text/csv') setContentDisposition('_output.csv') output = self.getExportCSV() return lambda: [(yield x) for x in output.getvalue()]