Пример #1
0
 def _getAndCacheImage(self, item, imageFunc, checkAndCreate, keydict,
                       **kwargs):
     if 'fill' in keydict and (keydict['fill']).lower() == 'none':
         del keydict['fill']
     keydict = {k: v for k, v in six.viewitems(keydict) if v is not None}
     key = json.dumps(keydict, sort_keys=True, separators=(',', ':'))
     existing = File().findOne({
         'attachedToType': 'item',
         'attachedToId': item['_id'],
         'isLargeImageThumbnail': True,
         'thumbnailKey': key
     })
     if existing:
         if checkAndCreate:
             return True
         if kwargs.get('contentDisposition') != 'attachment':
             contentDisposition = 'inline'
         else:
             contentDisposition = kwargs['contentDisposition']
         return File().download(existing,
                                contentDisposition=contentDisposition)
     tileSource = self._loadTileSource(item, **kwargs)
     result = getattr(tileSource, imageFunc)(**kwargs)
     if result is None:
         thumbData, thumbMime = b'', 'application/octet-stream'
     else:
         thumbData, thumbMime = result
     # The logic on which files to save could be more sophisticated.
     maxThumbnailFiles = int(Setting().get(
         constants.PluginSettings.LARGE_IMAGE_MAX_THUMBNAIL_FILES))
     saveFile = maxThumbnailFiles > 0
     if saveFile:
         # Make sure we don't exceed the desired number of thumbnails
         self.removeThumbnailFiles(item, maxThumbnailFiles - 1)
         # Save the thumbnail as a file
         thumbfile = Upload().uploadFromFile(six.BytesIO(thumbData),
                                             size=len(thumbData),
                                             name='_largeImageThumbnail',
                                             parentType='item',
                                             parent=item,
                                             user=None,
                                             mimeType=thumbMime,
                                             attachParent=True)
         if not len(thumbData) and 'received' in thumbfile:
             thumbfile = Upload().finalizeUpload(
                 thumbfile,
                 Assetstore().load(thumbfile['assetstoreId']))
         thumbfile.update({
             'isLargeImageThumbnail': True,
             'thumbnailKey': key,
         })
         # Ideally, we would check that the file is still wanted before we
         # save it.  This is probably impossible without true transactions in
         # Mongo.
         File().save(thumbfile)
     # Return the data
     return thumbData, thumbMime
Пример #2
0
    def _getAndCacheImageOrData(
            self, item, imageFunc, checkAndCreate, keydict, pickleCache=False, **kwargs):
        """
        Get a file associated with an image that can be generated by a
        function.

        :param item: the idem to process.
        :param imageFunc: the function to call to generate a file.
        :param checkAndCreate: False to return the data, creating and caching
            it if needed.  True to return True if the data is already in cache,
            or to create the data, cache, and return it if not.  'nosave' to
            return data from the cache if present, or generate the data but do
            not return it if not in the cache.  'check' to just return True or
            False to report if it is in the cache.
        :param keydict: a dictionary of values to use for the cache key.
        :param pickleCache: if True, the results of the function are pickled to
            preserver them.  If Fales, the results can be saved as a file
            directly.
        :params **kwargs: passed to the tile source and to the imageFunc.  May
            contain contentDisposition to determine how results are returned.
        :returns:
        """
        if 'fill' in keydict and (keydict['fill']).lower() == 'none':
            del keydict['fill']
        keydict = {k: v for k, v in keydict.items() if v is not None and not k.startswith('_')}
        key = json.dumps(keydict, sort_keys=True, separators=(',', ':'))
        existing = File().findOne({
            'attachedToType': 'item',
            'attachedToId': item['_id'],
            'isLargeImageThumbnail' if not pickleCache else 'isLargeImageData': True,
            'thumbnailKey': key,
        })
        if existing:
            if checkAndCreate and checkAndCreate != 'nosave':
                return True
            if kwargs.get('contentDisposition') != 'attachment':
                contentDisposition = 'inline'
            else:
                contentDisposition = kwargs['contentDisposition']
            if pickleCache:
                data = File().open(existing).read()
                return pickle.loads(data), 'application/octet-stream'
            return File().download(existing, contentDisposition=contentDisposition)
        if checkAndCreate == 'check':
            return False
        tileSource = self._loadTileSource(item, **kwargs)
        result = getattr(tileSource, imageFunc)(**kwargs)
        if result is None:
            imageData, imageMime = b'', 'application/octet-stream'
        elif pickleCache:
            imageData, imageMime = result, 'application/octet-stream'
        else:
            imageData, imageMime = result
        saveFile = True
        if not pickleCache:
            # The logic on which files to save could be more sophisticated.
            maxThumbnailFiles = int(Setting().get(
                constants.PluginSettings.LARGE_IMAGE_MAX_THUMBNAIL_FILES))
            saveFile = maxThumbnailFiles > 0
            # Make sure we don't exceed the desired number of thumbnails
            self.removeThumbnailFiles(
                item, maxThumbnailFiles - 1, imageKey=keydict.get('imageKey') or 'none')
        if (saveFile and checkAndCreate != 'nosave' and (
                pickleCache or isinstance(imageData, bytes))):
            dataStored = imageData if not pickleCache else pickle.dumps(imageData, protocol=4)
            # Save the data as a file
            try:
                datafile = Upload().uploadFromFile(
                    io.BytesIO(dataStored), size=len(dataStored),
                    name='_largeImageThumbnail', parentType='item', parent=item,
                    user=None, mimeType=imageMime, attachParent=True)
                if not len(dataStored) and 'received' in datafile:
                    datafile = Upload().finalizeUpload(
                        datafile, Assetstore().load(datafile['assetstoreId']))
                datafile.update({
                    'isLargeImageThumbnail' if not pickleCache else 'isLargeImageData': True,
                    'thumbnailKey': key,
                })
                # Ideally, we would check that the file is still wanted before
                # we save it.  This is probably impossible without true
                # transactions in Mongo.
                File().save(datafile)
            except (GirderException, PermissionError):
                logger.warning('Could not cache data for large image')
        return imageData, imageMime