示例#1
0
    def downloadMultiple(self, params):
        include = params.get('include', 'all')
        if include not in {'all', 'images', 'metadata'}:
            raise ValidationException(
                'Param "include" must be one of: "all", "images", "metadata"', 'include')

        if 'filter' in params and 'imageIds' in params:
            raise RestException('Only one of "filter" or "imageIds" may be specified.')

        if 'filter' in params:
            query = self._parseFilter(params['filter'])
        elif 'imageIds' in params:
            query = self._parseImageIds(params['imageIds'])
        else:
            query = {}

        user = self.getCurrentUser()
        downloadFileName = 'ISIC-images'

        images = Image().filterResultsByPermission(
            Image().find(query, sort=[('name', 1)]),
            user=user, level=AccessType.READ, limit=0, offset=0)
        # Prevent cursor timeouts by eagerly evaluating the whole query
        images = list(images)
        imagesZipGenerator = self._imagesZipGenerator(downloadFileName, images, include)

        setResponseHeader('Content-Type', 'application/zip')
        setResponseHeader('Content-Disposition', 'attachment; filename="%s.zip"' % downloadFileName)
        return lambda: imagesZipGenerator
示例#2
0
 def getTilesRegion(self, item, params):
     params = self._parseParams(params, True, [
         ('left', float, 'region', 'left'),
         ('top', float, 'region', 'top'),
         ('right', float, 'region', 'right'),
         ('bottom', float, 'region', 'bottom'),
         ('regionWidth', float, 'region', 'width'),
         ('regionHeight', float, 'region', 'height'),
         ('units', str, 'region', 'units'),
         ('width', int, 'output', 'maxWidth'),
         ('height', int, 'output', 'maxHeight'),
         ('magnification', float, 'scale', 'magnification'),
         ('mm_x', float, 'scale', 'mm_x'),
         ('mm_y', float, 'scale', 'mm_y'),
         ('exact', bool, 'scale', 'exact'),
         ('encoding', str),
         ('jpegQuality', int),
         ('jpegSubsampling', int),
     ])
     try:
         regionData, regionMime = self.imageItemModel.getRegion(
             item, **params)
     except TileGeneralException as e:
         raise RestException(e.message)
     except ValueError as e:
         raise RestException('Value Error: %s' % e.message)
     setResponseHeader('Content-Type', regionMime)
     setRawResponse()
     return regionData
    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')
        if contentDisposition == 'inline':
            setResponseHeader(
                'Content-Disposition',
                'inline; filename="%s"' % file['name'])
        else:
            setResponseHeader(
                'Content-Disposition',
                'attachment; filename="%s"' % file['name'])
        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']))
示例#4
0
    def _getTile(self, item, z, x, y, imageArgs):
        """
        Get an large image tile.

        :param item: the item to get a tile from.
        :param z: tile layer number (0 is the most zoomed-out).
        .param x: the X coordinate of the tile (0 is the left side).
        .param y: the Y coordinate of the tile (0 is the top).
        :param imageArgs: additional arguments to use when fetching image data.
        :return: a function that returns the raw image data.
        """
        try:
            x, y, z = int(x), int(y), int(z)
        except ValueError:
            raise RestException('x, y, and z must be integers', code=400)
        if x < 0 or y < 0 or z < 0:
            raise RestException('x, y, and z must be positive integers',
                                code=400)
        try:
            tileData, tileMime = self.imageItemModel.getTile(
                item, x, y, z, **imageArgs)
        except TileGeneralException as e:
            raise RestException(e.message, code=404)
        setResponseHeader('Content-Type', tileMime)
        setRawResponse()
        return tileData
示例#5
0
 def getTile(self, itemId, z, x, y, params):
     item = loadmodelcache.loadModel(
         self, 'item', id=itemId, allowCookie=True, level=AccessType.READ)
     # Explicitly set a expires time to encourage browsers to cache this for
     # a while.
     setResponseHeader('Expires', cherrypy.lib.httputil.HTTPDate(
         cherrypy.serving.response.time + 600))
     return self._getTile(item, z, x, y, params)
示例#6
0
    def thumbnail(self, image, params):
        width = int(params.get('width', 256))
        height = int(params.get('height', 256))
        thumbData, thumbMime = ImageItem().getThumbnail(image, width=width, height=height)

        # Only setRawResponse now, as this handler may return a JSON error
        # earlier
        setRawResponse()
        setResponseHeader('Content-Type', thumbMime)
        return thumbData
示例#7
0
    def getStudy(self, study, params):
        if params.get('format') == 'csv':
            setResponseHeader('Content-Type', 'text/csv')
            setResponseHeader('Content-Disposition',
                              'attachment; filename="%s.csv"' % study['name'])
            return functools.partial(self._getStudyCSVStream, study)

        else:
            user = self.getCurrentUser()
            return Study().filter(study, user)
示例#8
0
 def testAnalysisXmlDetection(self, params):
     """Return the nuclei detection XML spec as a test case."""
     xml_file = os.path.abspath(
         os.path.join(os.path.dirname(__file__), 'test_files',
                      'test_analysis_detection.xml'))
     with open(xml_file) as f:
         xml = f.read()
     setResponseHeader('Content-Type', 'application/xml')
     setRawResponse()
     return xml
示例#9
0
    def thumbnail(self, image, params):
        width = int(params.get('width', 256))
        height = int(params.get('height', 256))
        thumbData, thumbMime = ImageItem().getThumbnail(image, width=width, height=height)

        # Only setRawResponse now, as this handler may return a JSON error
        # earlier
        setRawResponse()
        setResponseHeader('Content-Type', thumbMime)
        return thumbData
示例#10
0
 def testAnalysisXmlFeatures(self, params):
     """Return the nuclei feature classification XML spec as a test case."""
     xml_file = os.path.abspath(
         os.path.join(os.path.dirname(__file__), '..', 'histomicstk', 'cli',
                      'ComputeNucleiFeatures', 'ComputeNucleiFeatures.xml'))
     with open(xml_file) as f:
         xml = f.read()
     setResponseHeader('Content-Type', 'application/xml')
     setRawResponse()
     return xml
示例#11
0
    def getStudy(self, study, params):
        if params.get('format') == 'csv':
            setResponseHeader('Content-Type', 'text/csv')
            setResponseHeader('Content-Disposition',
                              'attachment; filename="%s.csv"' % study['name'])
            return functools.partial(self._getStudyCSVStream, study)

        else:
            user = self.getCurrentUser()
            return Study().filter(study, user)
示例#12
0
    def downloadFile(self, file, offset=0, headers=True, endByte=None,
                     contentDisposition=None, extraParameters=None, **kwargs):
        """
        Returns a generator function that will be used to stream the file from
        the database to the response.
        """
        if endByte is None or endByte > file['size']:
            endByte = file['size']

        if headers:
            setResponseHeader('Accept-Ranges', 'bytes')
            self.setContentHeaders(file, offset, endByte, contentDisposition)

        # If the file is empty, we stop here
        if endByte - offset <= 0:
            return lambda: ''

        n = 0
        chunkOffset = 0

        # We must "seek" to the correct chunk index and local offset
        if offset > 0:
            n = offset // file['chunkSize']
            chunkOffset = offset % file['chunkSize']

        cursor = self.chunkColl.find({
            'uuid': file['chunkUuid'],
            'n': {'$gte': n}
        }, projection=['data']).sort('n', pymongo.ASCENDING)

        def stream():
            co = chunkOffset  # Can't assign to outer scope without "nonlocal"
            position = offset
            shouldBreak = False

            for chunk in cursor:
                chunkLen = len(chunk['data'])

                if position + chunkLen - co > endByte:
                    chunkLen = endByte - position + co
                    shouldBreak = True

                yield chunk['data'][co:chunkLen]

                if shouldBreak:
                    break

                position += chunkLen - co

                if co > 0:
                    co = 0

        return stream
    def downloadFile(self, file, offset=0, headers=True, endByte=None,
                     contentDisposition=None, extraParameters=None, **kwargs):
        """
        Returns a generator function that will be used to stream the file from
        the database to the response.
        """
        if endByte is None or endByte > file['size']:
            endByte = file['size']

        if headers:
            setResponseHeader('Accept-Ranges', 'bytes')
            self.setContentHeaders(file, offset, endByte, contentDisposition)

        # If the file is empty, we stop here
        if endByte - offset <= 0:
            return lambda: ''

        n = 0
        chunkOffset = 0

        # We must "seek" to the correct chunk index and local offset
        if offset > 0:
            n = offset // file['chunkSize']
            chunkOffset = offset % file['chunkSize']

        cursor = self.chunkColl.find({
            'uuid': file['chunkUuid'],
            'n': {'$gte': n}
        }, projection=['data']).sort('n', pymongo.ASCENDING)

        def stream():
            co = chunkOffset  # Can't assign to outer scope without "nonlocal"
            position = offset
            shouldBreak = False

            for chunk in cursor:
                chunkLen = len(chunk['data'])

                if position + chunkLen - co > endByte:
                    chunkLen = endByte - position + co
                    shouldBreak = True

                yield chunk['data'][co:chunkLen]

                if shouldBreak:
                    break

                position += chunkLen - co

                if co > 0:
                    co = 0

        return stream
示例#14
0
 def getTile(self, itemId, z, x, y, params):
     _adjustParams(params)
     item = loadmodelcache.loadModel(
         self, 'item', id=itemId, allowCookie=True, level=AccessType.READ)
     # Explicitly set a expires time to encourage browsers to cache this for
     # a while.
     setResponseHeader('Expires', cherrypy.lib.httputil.HTTPDate(
         cherrypy.serving.response.time + 600))
     redirect = params.get('redirect', False)
     if redirect not in ('any', 'exact', 'encoding'):
         redirect = False
     return self._getTile(item, z, x, y, params, mayRedirect=redirect)
示例#15
0
    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
示例#16
0
    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
示例#17
0
 def _forward(self):
     """
     Forward a request to the same path with a slash added.
     """
     result = '\n'.join([
         '<html>', '<head><title>301 Moved Permanently</title></head>',
         '<body>', '<center><h1>301 Moved Permanently</h1></center>',
         '</body>', '</html>'])
     setResponseHeader('Location', cherrypy.request.path_info + '/')
     setResponseHeader('Content-Type', 'text/html')
     setRawResponse()
     cherrypy.response.status = 301
     return result.encode('utf8')
示例#18
0
 def getTile(self, itemId, z, x, y, params):
     item = loadmodelcache.loadModel(self,
                                     'item',
                                     id=itemId,
                                     allowCookie=True,
                                     level=AccessType.READ)
     # Explicitly set a expires time to encourage browsers to cache this for
     # a while.
     setResponseHeader(
         'Expires',
         cherrypy.lib.httputil.HTTPDate(cherrypy.serving.response.time +
                                        600))
     return self._getTile(item, z, x, y, params)
示例#19
0
 def getTile(self, image, z, x, y, params):
     try:
         x, y, z = int(x), int(y), int(z)
     except ValueError:
         raise RestException('x, y, and z must be integers')
     if x < 0 or y < 0 or z < 0:
         raise RestException('x, y, and z must be positive integers')
     try:
         tileData, tileMime = ImageItem().getTile(image, x, y, z)
     except TileGeneralException as e:
         raise RestException(e.message, code=404)
     setResponseHeader('Content-Type', tileMime)
     setRawResponse()
     return tileData
示例#20
0
    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
示例#21
0
    def thumbnail(self, segmentation, params):
        contentDisp = params.get('contentDisposition', None)
        if contentDisp is not None and contentDisp not in {'inline', 'attachment'}:
            raise ValidationException(f'Unallowed contentDisposition type "{contentDisp}".',
                                      'contentDisposition')

        # TODO: convert this to make Segmentation use an AccessControlMixin
        image = Image().load(
            segmentation['imageId'], level=AccessType.READ, user=self.getCurrentUser(), exc=True)

        width = int(params.get('width', 256))

        thumbnailImageStream = Segmentation().boundaryThumbnail(segmentation, image, width)
        if thumbnailImageStream is None:
            raise RestException('This segmentation is failed, and thus has no thumbnail.', code=410)
        thumbnailImageData = thumbnailImageStream.getvalue()

        # Only setRawResponse now, as this handler may return a JSON error
        # earlier
        setRawResponse()
        setResponseHeader('Content-Type', 'image/jpeg')
        contentName = f'{image["name"]}_segmentation_thumbnail.jpg'
        if contentDisp == 'inline':
            setResponseHeader('Content-Disposition', f'inline; filename="{contentName}"')
        else:
            setResponseHeader('Content-Disposition', f'attachment; filename="{contentName}"')
        setResponseHeader('Content-Length', len(thumbnailImageData))

        return thumbnailImageData
示例#22
0
 def getTile(self, image, z, x, y, params):
     try:
         x, y, z = int(x), int(y), int(z)
     except ValueError:
         raise RestException('x, y, and z must be integers')
     if x < 0 or y < 0 or z < 0:
         raise RestException('x, y, and z must be positive integers')
     try:
         tileData, tileMime = ImageItem().getTile(image, x, y, z)
     except TileGeneralException as e:
         raise RestException(e.message, code=404)
     setResponseHeader('Content-Type', tileMime)
     setRawResponse()
     return tileData
示例#23
0
    def thumbnail(self, segmentation, params):
        contentDisp = params.get('contentDisposition', None)
        if contentDisp is not None and contentDisp not in {'inline', 'attachment'}:
            raise ValidationException('Unallowed contentDisposition type "%s".' % contentDisp,
                                      'contentDisposition')

        # TODO: convert this to make Segmentation use an AccessControlMixin
        image = Image().load(
            segmentation['imageId'], level=AccessType.READ, user=self.getCurrentUser(), exc=True)

        width = int(params.get('width', 256))

        thumbnailImageStream = Segmentation().boundaryThumbnail(segmentation, image, width)
        if thumbnailImageStream is None:
            raise RestException('This segmentation is failed, and thus has no thumbnail.', code=410)
        thumbnailImageData = thumbnailImageStream.getvalue()

        # Only setRawResponse now, as this handler may return a JSON error
        # earlier
        setRawResponse()
        setResponseHeader('Content-Type', 'image/jpeg')
        contentName = '%s_segmentation_thumbnail.jpg' % image['name']
        if contentDisp == 'inline':
            setResponseHeader('Content-Disposition', 'inline; filename="%s"' % contentName)
        else:
            setResponseHeader('Content-Disposition', 'attachment; filename="%s"' % contentName)
        setResponseHeader('Content-Length', len(thumbnailImageData))

        return thumbnailImageData
示例#24
0
    def getAnnotationMarkupRendered(self, annotation, featureId, params):
        contentDisp = params.get('contentDisposition', None)
        if contentDisp is not None and contentDisp not in {'inline', 'attachment'}:
            raise ValidationException('Unallowed contentDisposition type "%s".' % contentDisp,
                                      'contentDisposition')

        self._ensureMarkup(annotation, featureId)

        renderData = Annotation().renderMarkup(annotation, featureId)

        renderEncodedStream = ScikitSegmentationHelper.writeImage(renderData, 'jpeg')
        renderEncodedData = renderEncodedStream.getvalue()

        # Only setRawResponse now, as this handler may return a JSON error earlier
        setRawResponse()
        setResponseHeader('Content-Type', 'image/jpeg')
        contentName = 'annotation_%s_%s.jpg' % (
            annotation['_id'],
            # Rename features to ensure the file is downloadable on Windows
            featureId.replace(' : ', ' ; ').replace('/', ',')
        )
        if contentDisp == 'inline':
            setResponseHeader(
                'Content-Disposition',
                'inline; filename="%s"' % contentName)
        else:
            setResponseHeader(
                'Content-Disposition',
                'attachment; filename="%s"' % contentName)
        setResponseHeader('Content-Length', len(renderEncodedData))

        return renderEncodedData
示例#25
0
def _getHdf5Dataset(self, item):
    try:
        setResponseHeader('Content-Type', 'image/png')
        setRawResponse()
        hdf5Path = [i for i in item['meta']
                    if 'hdf5Path' in i.keys()][0]['hdf5Path']
        pathInHdf5 = [i for i in item['meta']
                      if 'pathInHdf5' in i.keys()][0]['pathInHdf5']
        figure = render_hdf5_dataset(hdf5Path, pathInHdf5)
        buf = BytesIO()
        figure.savefig(buf, format='png')
        return b64encode(buf.getvalue())
    except:
        pass
示例#26
0
    def getAnnotationMarkupRendered(self, annotation, featureId, params):
        contentDisp = params.get('contentDisposition', None)
        if contentDisp is not None and contentDisp not in {
                'inline', 'attachment'
        }:
            raise ValidationException(
                f'Unallowed contentDisposition type "{contentDisp}".',
                'contentDisposition')

        self._ensureMarkup(annotation, featureId)

        renderData = Annotation().renderMarkup(annotation, featureId)

        renderEncodedStream = ScikitSegmentationHelper.writeImage(
            renderData, 'jpeg')
        renderEncodedData = renderEncodedStream.getvalue()

        # Only setRawResponse now, as this handler may return a JSON error earlier
        setRawResponse()
        setResponseHeader('Content-Type', 'image/jpeg')
        contentName = 'annotation_%s_%s.jpg' % (
            annotation['_id'],
            # Rename features to ensure the file is downloadable on Windows
            featureId.replace(' : ', ' ; ').replace('/', ','))
        if contentDisp == 'inline':
            setResponseHeader('Content-Disposition',
                              f'inline; filename="{contentName}"')
        else:
            setResponseHeader('Content-Disposition',
                              f'attachment; filename="{contentName}"')
        setResponseHeader('Content-Length', str(len(renderEncodedData)))

        return renderEncodedData
示例#27
0
文件: __init__.py 项目: girder/girder
    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
示例#28
0
 def getDZITile(self, item, level, xandy, params):
     _adjustParams(params)
     tilesize = int(params.get('tilesize', 256))
     if tilesize & (tilesize - 1):
         raise RestException('Invalid tilesize', code=400)
     overlap = int(params.get('overlap', 0))
     if overlap < 0:
         raise RestException('Invalid overlap', code=400)
     x, y = [int(xy) for xy in xandy.split('.')[0].split('_')]
     _handleETag('getDZITile', item, level, xandy, params)
     metadata = self.imageItemModel.getMetadata(item, **params)
     level = int(level)
     maxlevel = int(math.ceil(math.log(max(
         metadata['sizeX'], metadata['sizeY'])) / math.log(2)))
     if level < 1 or level > maxlevel:
         raise RestException('level must be between 1 and the image scale',
                             code=400)
     lfactor = 2 ** (maxlevel - level)
     region = {
         'left': (x * tilesize - overlap) * lfactor,
         'top': (y * tilesize - overlap) * lfactor,
         'right': ((x + 1) * tilesize + overlap) * lfactor,
         'bottom': ((y + 1) * tilesize + overlap) * lfactor,
     }
     width = height = tilesize + overlap * 2
     if region['left'] < 0:
         width += int(region['left'] / lfactor)
         region['left'] = 0
     if region['top'] < 0:
         height += int(region['top'] / lfactor)
         region['top'] = 0
     if region['left'] >= metadata['sizeX']:
         raise RestException('x is outside layer', code=400)
     if region['top'] >= metadata['sizeY']:
         raise RestException('y is outside layer', code=400)
     if region['left'] < metadata['sizeX'] and region['right'] > metadata['sizeX']:
         region['right'] = metadata['sizeX']
         width = int(math.ceil(float(region['right'] - region['left']) / lfactor))
     if region['top'] < metadata['sizeY'] and region['bottom'] > metadata['sizeY']:
         region['bottom'] = metadata['sizeY']
         height = int(math.ceil(float(region['bottom'] - region['top']) / lfactor))
     regionData, regionMime = self.imageItemModel.getRegion(
         item,
         region=region,
         output=dict(maxWidth=width, maxHeight=height),
         **params)
     setResponseHeader('Content-Type', regionMime)
     setRawResponse()
     return regionData
示例#29
0
    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
示例#30
0
    def scan_positions(self, id, user, type):
        path = self._get_path_to_type(type)
        if type == 'electron':
            return self._get_h5_dataset(id, user, path)
        elif type == 'raw':
            setResponseHeader('Content-Type', 'application/octet-stream')

            def _stream():
                with self._open_h5py_file(id, user) as rf:
                    dataset = rf[path]
                    array = np.array([i for i in range(dataset.shape[0])])
                    yield array.tobytes()

            return _stream

        raise RestException('In scan_positions, unknown type: ' + type)
示例#31
0
    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
示例#32
0
    def file_download(self, event, path, root, user=None):
        fobj = self.vFile(path, root)

        rangeHeader = cherrypy.lib.httputil.get_ranges(
            cherrypy.request.headers.get("Range"), fobj.get("size", 0)
        )
        # 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]
        else:
            endByte = min(
                int(event.info["params"].get("endByte", fobj["size"])), fobj["size"]
            )
            offset = int(event.info["params"].get("offset", "0"))

        setResponseHeader("Accept-Ranges", "bytes")
        setResponseHeader("Content-Type", "application/octet-stream")
        setResponseHeader("Content-Length", max(endByte - offset, 0))
        if (offset or endByte < fobj["size"]) and fobj["size"]:
            setResponseHeader(
                "Content-Range", "bytes %d-%d/%d" % (offset, endByte - 1, fobj["size"])
            )
        disp = event.info["params"].get("contentDisposition", "attachment")
        setResponseHeader(
            "Content-Disposition", '{}; filename="{}"'.format(disp, fobj["name"])
        )

        def stream():
            bytesRead = offset
            with path.open(mode="rb") as f:
                if offset > 0:
                    f.seek(offset)

                while True:
                    readLen = min(BUF_SIZE, endByte - bytesRead)
                    if readLen <= 0:
                        break

                    data = f.read(readLen)
                    bytesRead += readLen

                    # if not data:
                    #    break
                    yield data

        event.preventDefault().addResponse(stream)
示例#33
0
    def downloadFile(self,
                     file,
                     offset=0,
                     headers=True,
                     endByte=None,
                     contentDisposition=None,
                     extraParameters=None,
                     **kwargs):
        """
        Returns a generator function that will be used to stream the file from
        disk to the response.
        """
        if endByte is None or endByte > file['size']:
            endByte = file['size']

        path = self.fullPath(file)

        if not os.path.isfile(path):
            raise GirderException(
                'File %s does not exist.' % path,
                'girder.utility.filesystem_assetstore_adapter.'
                'file-does-not-exist')

        if headers:
            setResponseHeader('Accept-Ranges', 'bytes')
            self.setContentHeaders(file, offset, endByte, contentDisposition)

        def stream():
            bytesRead = offset
            with open(path, 'rb') as f:
                if offset > 0:
                    f.seek(offset)

                while True:
                    readLen = min(BUF_SIZE, endByte - bytesRead)
                    if readLen <= 0:
                        break

                    data = f.read(readLen)
                    bytesRead += readLen

                    if not data:
                        break
                    yield data

        return stream
示例#34
0
    def downloadFile(self,
                     file,
                     offset=0,
                     headers=True,
                     endByte=None,
                     contentDisposition=None,
                     extraParameters=None,
                     **kwargs):
        if endByte is None or endByte > file['size']:
            endByte = file['size']

        if headers:
            setResponseHeader('Accept-Ranges', 'bytes')
            self.setContentHeaders(file, offset, endByte, contentDisposition)

        if file['hdfs'].get('imported'):
            path = file['hdfs']['path']
        else:
            path = self._absPath(file)

        def stream():
            position = 0
            fileStream = self.client.cat([path]).next()
            shouldBreak = False
            for chunk in fileStream:
                chunkLen = len(chunk)

                if position < offset:
                    if position + chunkLen > offset:
                        if position + chunkLen > endByte:
                            chunkLen = endByte - position
                            shouldBreak = True
                        yield chunk[offset - position:chunkLen]
                else:
                    if position + chunkLen > endByte:
                        chunkLen = endByte - position
                        shouldBreak = True
                    yield chunk[:chunkLen]

                position += chunkLen

                if shouldBreak:
                    break

        return stream
示例#35
0
    def importAnnotation(self, folder, params):
        # TODO: Check if is a clip folder
        detectionItem, activitiesItem, typesItem = self._getAnnotationItems(folder)

        setResponseHeader('Content-Length', 1000000)

        def gen():
            self._importActivities(folder['_id'], activitiesItem)
            self._importTypes(folder['_id'], typesItem)
            lastProgress = 0
            import math
            for percentage in self._importDetection(folder['_id'], detectionItem):
                progress = int(math.floor(percentage * 100))
                if lastProgress != progress:
                    yield '1' * (progress - lastProgress) * 10000
                    lastProgress = progress
            yield '1' * (100 - lastProgress) * 10000
        return gen
示例#36
0
    def getTile(self, itemId, z, x, y, params):
        _adjustParams(params)
        item = loadmodelcache.loadModel(
            self, 'item', id=itemId, allowCookie=True, level=AccessType.READ)
        # Explicitly set a expires time to encourage browsers to cache this for
        # a while.
        setResponseHeader('Expires', cherrypy.lib.httputil.HTTPDate(
            cherrypy.serving.response.time + 600))
        redirect = params.get('redirect', False)
        if redirect not in ('any', 'exact', 'encoding'):
            redirect = False
        typeList = [
            ('normalize', bool),
            ('normalizeMin', float),
            ('normalizeMax', float),
            ('label', bool),
            ('invertLabel', bool),
            ('flattenLabel', bool),
            ('oneHot', bool),
            ('bit', int),
        ]
        params = self._parseParams(params, True, typeList)

        if 'exclude' in params:
            # TODO: error handling
            params['exclude'] = [int(s) for s in params['exclude'].split(',')]
        if Colormap and 'colormapId' in params:
            # colormap = Colormap().load(params['colormapId'],
            #                            force=True, exc=True)
            #                            user=self.getCurrentUser(),
            #                            level=AccessType.READ)
            colormap = Colormap().load(params['colormapId'],
                                       force=True, exc=True)
            del params['colormapId']
            if 'bit' in params:
                params['colormap'] = colormap['colormap']
            else:
                # TODO: abstract in colormap
                try:
                    params['colormap'] = bytearray(colormap['binary'])
                except (KeyError, TypeError):
                    raise RestException('Invalid colormap on server',
                                        code=500)
        return self._getTile(item, z, x, y, params, mayRedirect=redirect)
示例#37
0
def _handleETag(key, item, *args, **kwargs):
    """
    Add or check an ETag header.

    :param key: key for making a distinc etag.
    :param item: item used for the item _id and updated timestamp.
    :param *args, **kwargs: additional arguments for generating an etag.
    """
    etag = hashlib.md5(strhash(key, str(item['_id']), *args, **kwargs).encode()).hexdigest()
    setResponseHeader('ETag', etag)
    conditions = [str(x) for x in cherrypy.request.headers.elements('If-Match') or []]
    if conditions and not (conditions == ['*'] or etag in conditions):
        raise cherrypy.HTTPError(
            412, 'If-Match failed: ETag %r did not match %r' % (etag, conditions))
    conditions = [str(x) for x in cherrypy.request.headers.elements('If-None-Match') or []]
    if conditions == ['*'] or etag in conditions:
        raise cherrypy.HTTPRedirect([], 304)
    # Explicitly set a max-ago to recheck the cahe after a while
    setResponseHeader('Cache-control', 'max-age=600')
示例#38
0
    def all_frames(self, id, user, type, limit=None, offset=None):
        path = self._get_path_to_type(type)

        # Ensure limit and offset are reasonable
        with self._open_h5py_file(id, user) as rf:
            limit, offset = self._check_limit_and_offset(
                rf[path], limit, offset)

        setResponseHeader('Content-Type', 'application/octet-stream')

        def _stream():
            nonlocal id
            nonlocal user
            with self._open_h5py_file(id, user) as rf:
                dataset = rf[path]
                for data in self._get_vlen_dataset_in_chunks(
                        dataset, limit, offset):
                    yield msgpack.packb(data, use_bin_type=True)

        return _stream
示例#39
0
 def getTilesThumbnail(self, item, params):
     params = self._parseParams(params, True, [
         ('width', int),
         ('height', int),
         ('jpegQuality', int),
         ('jpegSubsampling', int),
         ('encoding', str),
     ])
     try:
         result = self.imageItemModel.getThumbnail(item, **params)
     except TileGeneralException as e:
         raise RestException(e.message)
     except ValueError as e:
         raise RestException('Value Error: %s' % e.message)
     if not isinstance(result, tuple):
         return result
     thumbData, thumbMime = result
     setResponseHeader('Content-Type', thumbMime)
     setRawResponse()
     return thumbData
示例#40
0
 def getTilesThumbnail(self, item, params):
     params = self._parseParams(params, True, [
         ('width', int),
         ('height', int),
         ('jpegQuality', int),
         ('jpegSubsampling', int),
         ('encoding', str),
     ])
     try:
         result = self.imageItemModel.getThumbnail(item, **params)
     except TileGeneralException as e:
         raise RestException(e.message)
     except ValueError as e:
         raise RestException('Value Error: %s' % e.message)
     if not isinstance(result, tuple):
         return result
     thumbData, thumbMime = result
     setResponseHeader('Content-Type', thumbMime)
     setRawResponse()
     return thumbData
示例#41
0
 def getTilesRegion(self, item, params):
     _adjustParams(params)
     params = self._parseParams(params, True, [
         ('left', float, 'region', 'left'),
         ('top', float, 'region', 'top'),
         ('right', float, 'region', 'right'),
         ('bottom', float, 'region', 'bottom'),
         ('regionWidth', float, 'region', 'width'),
         ('regionHeight', float, 'region', 'height'),
         ('units', str, 'region', 'units'),
         ('unitsWH', str, 'region', 'unitsWH'),
         ('width', int, 'output', 'maxWidth'),
         ('height', int, 'output', 'maxHeight'),
         ('fill', str),
         ('magnification', float, 'scale', 'magnification'),
         ('mm_x', float, 'scale', 'mm_x'),
         ('mm_y', float, 'scale', 'mm_y'),
         ('exact', bool, 'scale', 'exact'),
         ('frame', int),
         ('encoding', str),
         ('jpegQuality', int),
         ('jpegSubsampling', int),
         ('tiffCompression', str),
         ('style', str),
         ('resample', 'boolOrInt'),
         ('contentDisposition', str),
     ])
     _handleETag('getTilesRegion', item, params)
     try:
         regionData, regionMime = self.imageItemModel.getRegion(
             item, **params)
     except TileGeneralException as e:
         raise RestException(e.args[0])
     except ValueError as e:
         raise RestException('Value Error: %s' % e.args[0])
     self._setContentDisposition(
         item, params.get('contentDisposition'), regionMime, 'region')
     setResponseHeader('Content-Type', regionMime)
     setRawResponse()
     return regionData
示例#42
0
    def getAnnotationMarkupMask(self, annotation, featureId, params):
        self._ensureMarkup(annotation, featureId)

        markupFile = Annotation().getMarkupFile(annotation, featureId)

        if markupFile:
            return File().download(markupFile, headers=True, contentDisposition='inline')
        else:
            image = Image().load(annotation['imageId'], force=True, exc=True)
            markupMask = numpy.zeros(
                (
                    image['meta']['acquisition']['pixelsY'],
                    image['meta']['acquisition']['pixelsX']
                ),
                dtype=numpy.uint8
            )
            markupMaskEncodedStream = ScikitSegmentationHelper.writeImage(markupMask, 'png')
            markupMaskEncodedData = markupMaskEncodedStream.getvalue()

            setRawResponse()
            setResponseHeader('Content-Type', 'image/png')
            contentName = 'annotation_%s_%s.png' % (
                annotation['_id'],
                # Rename features to ensure the file is downloadable on Windows
                featureId.replace(' : ', ' ; ').replace('/', ',')
            )
            setResponseHeader('Content-Disposition', 'inline; filename="%s"' % contentName)
            setResponseHeader('Content-Length', len(markupMaskEncodedData))

            return markupMaskEncodedData
    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']))
示例#44
0
    def getAnnotationMarkupMask(self, annotation, featureId, params):
        self._ensureMarkup(annotation, featureId)

        markupFile = Annotation().getMarkupFile(annotation, featureId)

        if markupFile:
            return File().download(markupFile,
                                   headers=True,
                                   contentDisposition='inline')
        else:
            image = Image().load(annotation['imageId'], force=True, exc=True)
            markupMask = numpy.zeros((image['meta']['acquisition']['pixelsY'],
                                      image['meta']['acquisition']['pixelsX']),
                                     dtype=numpy.uint8)
            markupMaskEncodedStream = ScikitSegmentationHelper.writeImage(
                markupMask, 'png')
            markupMaskEncodedData = markupMaskEncodedStream.getvalue()

            setRawResponse()
            setResponseHeader('Content-Type', 'image/png')
            contentName = 'annotation_%s_%s.png' % (
                annotation['_id'],
                # Rename features to ensure the file is downloadable on Windows
                featureId.replace(' : ', ' ; ').replace('/', ','))
            setResponseHeader('Content-Disposition',
                              f'inline; filename="{contentName}"')
            setResponseHeader('Content-Length',
                              str(len(markupMaskEncodedData)))

            return markupMaskEncodedData
    def downloadFile(self, file, offset=0, headers=True, endByte=None,
                     contentDisposition=None, extraParameters=None, **kwargs):
        """
        Returns a generator function that will be used to stream the file from
        disk to the response.
        """
        if endByte is None or endByte > file['size']:
            endByte = file['size']

        path = self.fullPath(file)

        if not os.path.isfile(path):
            raise GirderException(
                'File %s does not exist.' % path,
                'girder.utility.filesystem_assetstore_adapter.'
                'file-does-not-exist')

        if headers:
            setResponseHeader('Accept-Ranges', 'bytes')
            self.setContentHeaders(file, offset, endByte, contentDisposition)

        def stream():
            bytesRead = offset
            with open(path, 'rb') as f:
                if offset > 0:
                    f.seek(offset)

                while True:
                    readLen = min(BUF_SIZE, endByte - bytesRead)
                    if readLen <= 0:
                        break

                    data = f.read(readLen)
                    bytesRead += readLen

                    if not data:
                        break
                    yield data

        return stream
示例#46
0
    def downloadFile(self, file, offset=0, headers=True, endByte=None,
                     contentDisposition=None, extraParameters=None, **kwargs):
        if endByte is None or endByte > file['size']:
            endByte = file['size']

        if headers:
            setResponseHeader('Accept-Ranges', 'bytes')
            self.setContentHeaders(file, offset, endByte, contentDisposition)

        if file['hdfs'].get('imported'):
            path = file['hdfs']['path']
        else:
            path = self._absPath(file)

        def stream():
            position = 0
            fileStream = self.client.cat([path]).next()
            shouldBreak = False
            for chunk in fileStream:
                chunkLen = len(chunk)

                if position < offset:
                    if position + chunkLen > offset:
                        if position + chunkLen > endByte:
                            chunkLen = endByte - position
                            shouldBreak = True
                        yield chunk[offset - position:chunkLen]
                else:
                    if position + chunkLen > endByte:
                        chunkLen = endByte - position
                        shouldBreak = True
                    yield chunk[:chunkLen]

                position += chunkLen

                if shouldBreak:
                    break
        return stream
示例#47
0
    def renderAnnotation(self, annotation, params):
        Study = self.model('study', 'isic_archive')
        Annotation = self.model('annotation', 'isic_archive')
        contentDisp = params.get('contentDisposition', None)
        if contentDisp is not None and contentDisp not in {'inline', 'attachment'}:
            raise ValidationException('Unallowed contentDisposition type "%s".' % contentDisp,
                                      'contentDisposition')

        self.requireParams(['featureId'], params)
        featureId = params['featureId']

        study = Study.load(annotation['meta']['studyId'], force=True, exc=True)
        featureset = Study.getFeatureset(study)

        if not any(featureId == feature['id'] for feature in featureset['localFeatures']):
            raise ValidationException('Invalid featureId.', 'featureId')
        if Annotation.getState(annotation) != Study.State.COMPLETE:
            raise RestException('Only complete annotations can be rendered.')

        renderData = Annotation.renderAnnotation(annotation, featureId)

        renderEncodedStream = ScikitSegmentationHelper.writeImage(renderData, 'jpeg')
        renderEncodedData = renderEncodedStream.getvalue()

        # Only setRawResponse now, as this handler may return a JSON error
        # earlier
        setRawResponse()
        setResponseHeader('Content-Type', 'image/jpeg')
        contentName = '%s_%s_annotation.jpg' % (
            annotation['_id'],
            featureId.replace('/', ',')  # TODO: replace with a better character
        )
        if contentDisp == 'inline':
            setResponseHeader(
                'Content-Disposition',
                'inline; filename="%s"' % contentName)
        else:
            setResponseHeader(
                'Content-Disposition',
                'attachment; filename="%s"' % contentName)
        setResponseHeader('Content-Length', len(renderEncodedData))

        return renderEncodedData
示例#48
0
    def downloadKeyFile(self, file, algo, params):
        self._validateAlgo(algo)

        if algo not in file:
            raise RestException('This file does not have the %s hash computed.' % algo)
        hash = file[algo]
        name = '.'.join((file['name'], algo))

        setResponseHeader('Content-Length', len(hash))
        setResponseHeader('Content-Type', 'text/plain')
        setResponseHeader('Content-Disposition', 'attachment; filename="%s"' % name)
        setRawResponse()

        return hash
示例#49
0
 def rawReturningText(self, params):
     setResponseHeader('Content-Type', 'text/plain')
     return u'this is not encoded \U0001F44D'