def test_generate_renditions_custom_crop(self): inserted = [] renditions = get_renditions_spec() with open(IMG_PATH, 'rb') as original: generated = generate_renditions(original, 'id', inserted, 'image', 'image/jpeg', renditions, self.app.media.url_for_media) # thumbnail should keep 4:3 ration self.assertIn('thumbnail', generated) self.assertEqual(160, generated['thumbnail']['width']) self.assertEqual(120, generated['thumbnail']['height']) # landscape should be cropped to 200x100 self.assertIn('landscape', generated) landscape = generated['landscape'] self.assertEqual(200, landscape['width']) self.assertEqual(100, landscape['height']) self.assertEqual(0, landscape['CropLeft']) self.assertEqual(400, landscape['CropRight']) self.assertEqual(50, landscape['CropTop']) self.assertEqual(250, landscape['CropBottom']) # portrait should be cropped to 150x200 self.assertIn('portrait', generated) portrait = generated['portrait'] self.assertEqual(150, portrait['width']) self.assertEqual(200, portrait['height']) self.assertEqual(0, portrait['CropTop']) self.assertEqual(300, portrait['CropBottom']) self.assertEqual(87, portrait['CropLeft']) self.assertEqual(312, portrait['CropRight'])
def on_create(self, docs): ''' Create corresponding item on file upload ''' for doc in docs: file, content_type, metadata = self.get_file_from_document(doc) inserted = [doc['media']] file_type = content_type.split('/')[0] try: update_dates_for(doc) doc['guid'] = generate_guid(type=GUID_TAG) doc.setdefault('_id', doc['guid']) doc['type'] = self.type_av.get(file_type) doc['version'] = 1 doc['versioncreated'] = utcnow() rendition_spec = config.RENDITIONS['picture'] renditions = generate_renditions(file, doc['media'], inserted, file_type, content_type, rendition_spec, url_for_media) doc['renditions'] = renditions doc['mimetype'] = content_type doc['filemeta'] = metadata if not doc.get('_import', None): doc['creator'] = set_user(doc) add_activity('uploaded media {{ name }}', name=doc.get('headline', doc.get('mimetype')), renditions=doc.get('renditions')) except Exception as io: logger.exception(io) for file_id in inserted: delete_file_on_error(doc, file_id) abort(500) on_create_media_archive()
def on_create(self, docs): ''' Create corresponding item on file upload ''' for doc in docs: file, content_type, metadata = self.get_file_from_document(doc) inserted = [doc['media']] file_type = content_type.split('/')[0] try: update_dates_for(doc) doc['guid'] = generate_guid(type=GUID_TAG) doc.setdefault('_id', doc['guid']) doc['type'] = self.type_av.get(file_type) doc['version'] = 1 doc['versioncreated'] = utcnow() rendition_spec = config.RENDITIONS['picture'] renditions = generate_renditions(file, doc['media'], inserted, file_type, content_type, rendition_spec, url_for_media) doc['renditions'] = renditions doc['mimetype'] = content_type doc['filemeta'] = metadata if not doc.get('_import', None): doc['creator'] = set_user(doc) add_activity('uploaded media {{ name }}', name=doc.get('headline', doc.get('mimetype')), renditions=doc.get('renditions')) except Exception as io: logger.exception(io) for file_id in inserted: delete_file_on_error(doc, file_id) abort(500) on_create_media_archive()
def store_file(self, doc, content, filename, content_type): res = process_file_from_stream(content, filename=filename, content_type=content_type) file_name, content_type, metadata = res cropping_data = self.get_cropping_data(doc) _, out = crop_image(content, filename, cropping_data) metadata['length'] = json.dumps(len(out.getvalue())) try: logger.debug('Going to save media file with %s ' % file_name) out.seek(0) id = app.media.put(out, filename=file_name, content_type=content_type, metadata=metadata) doc['media'] = id doc['mime_type'] = content_type doc['filemeta'] = decode_metadata(metadata) inserted = [doc['media']] file_type = content_type.split('/')[0] rendition_spec = config.RENDITIONS['avatar'] renditions = generate_renditions(out, doc['media'], inserted, file_type, content_type, rendition_spec, url_for_media) doc['renditions'] = renditions except Exception as io: logger.exception(io) for file_id in inserted: delete_file_on_error(doc, file_id) raise SuperdeskError(message='Generating renditions failed')
def crop_and_store_file(self, doc, content, filename, content_type): # retrieve file name and metadata from file file_name, content_type, metadata = process_file_from_stream( content, content_type=content_type) # crop the file if needed, can change the image size was_cropped, out = crop_image(content, filename, doc) # the length in metadata could be updated if it was cropped if was_cropped: file_name, content_type, metadata_after_cropped = process_file_from_stream( out, content_type=content_type) # when cropped, metadata are reseted. Then we update the previous metadata variable metadata['length'] = metadata_after_cropped['length'] try: logger.debug('Going to save media file with %s ' % file_name) out.seek(0) file_id = app.media.put(out, filename=file_name, content_type=content_type, resource=self.datasource, metadata=metadata) doc['media'] = file_id doc['mimetype'] = content_type set_filemeta(doc, decode_metadata(metadata)) inserted = [doc['media']] file_type = content_type.split('/')[0] rendition_spec = config.RENDITIONS['avatar'] renditions = generate_renditions(out, file_id, inserted, file_type, content_type, rendition_spec, url_for_media) doc['renditions'] = renditions except Exception as io: for file_id in inserted: delete_file_on_error(doc, file_id) raise SuperdeskApiError.internalError( 'Generating renditions failed', exception=io)
def on_create(self, docs): """Create corresponding item on file upload.""" for doc in docs: if 'media' not in doc or doc['media'] is None: abort(400, description="No media found") file, content_type, metadata = self.get_file_from_document(doc) inserted = [doc['media']] file_type = content_type.split('/')[0] self._set_metadata(doc) try: doc[ITEM_TYPE] = self.type_av.get(file_type) rendition_spec = get_renditions_spec() renditions = generate_renditions(file, doc['media'], inserted, file_type, content_type, rendition_spec, url_for_media) doc['renditions'] = renditions doc['mimetype'] = content_type set_filemeta(doc, metadata) add_activity('upload', 'uploaded media {{ name }}', 'archive', item=doc, name=doc.get('headline', doc.get('mimetype')), renditions=doc.get('renditions')) except Exception as io: logger.exception(io) for file_id in inserted: delete_file_on_error(doc, file_id) abort(500)
def crop_and_store_file(self, doc, content, filename, content_type): # retrieve file name and metadata from file file_name, content_type, metadata = process_file_from_stream(content, content_type=content_type) # crop the file if needed, can change the image size was_cropped, out = crop_image(content, filename, doc) # the length in metadata could be updated if it was cropped if was_cropped: file_name, content_type, metadata_after_cropped = process_file_from_stream(out, content_type=content_type) # when cropped, metadata are reseted. Then we update the previous metadata variable metadata['length'] = metadata_after_cropped['length'] try: logger.debug('Going to save media file with %s ' % file_name) out.seek(0) file_id = app.media.put(out, filename=file_name, content_type=content_type, resource=self.datasource, metadata=metadata) doc['media'] = file_id doc['mimetype'] = content_type doc['filemeta'] = decode_metadata(metadata) inserted = [doc['media']] file_type = content_type.split('/')[0] rendition_spec = config.RENDITIONS['avatar'] renditions = generate_renditions(out, file_id, inserted, file_type, content_type, rendition_spec, url_for_media) doc['renditions'] = renditions except Exception as io: logger.exception(io) for file_id in inserted: delete_file_on_error(doc, file_id) raise SuperdeskApiError.internalError('Generating renditions failed')
def setUp(self): super().setUp() dirname = os.path.dirname(os.path.realpath(__file__)) image_path = os.path.normpath( os.path.join(dirname, 'fixtures', self.filename)) content_type = mimetypes.guess_type(image_path)[0] guid = utils.generate_guid(type=GUID_TAG) self.item = { 'guid': guid, 'version': 1, '_id': guid, ITEM_TYPE: CONTENT_TYPE.PICTURE, 'mimetype': content_type, 'versioncreated': datetime.now() } with open(image_path, 'rb') as f: _, content_type, file_metadata = process_file_from_stream( f, content_type=content_type) f.seek(0) file_id = app.media.put(f, filename=self.filename, content_type=content_type, metadata=file_metadata) filemeta.set_filemeta(self.item, file_metadata) f.seek(0) rendition_spec = get_renditions_spec() renditions = generate_renditions(f, file_id, [file_id], 'image', content_type, rendition_spec, url_for_media) self.item['renditions'] = renditions archive = get_resource_service('archive') archive.post([self.item])
def setUp(self): super().setUp() dirname = os.path.dirname(os.path.realpath(__file__)) image_path = os.path.normpath(os.path.join(dirname, 'fixtures', self.filename)) content_type = mimetypes.guess_type(image_path)[0] guid = utils.generate_guid(type=GUID_TAG) self.item = {'guid': guid, 'version': 1, '_id': guid, ITEM_TYPE: CONTENT_TYPE.PICTURE, 'mimetype': content_type, 'versioncreated': datetime.now() } with open(image_path, 'rb') as f: _, content_type, file_metadata = process_file_from_stream(f, content_type=content_type) f.seek(0) file_id = app.media.put(f, filename=self.filename, content_type=content_type, metadata=file_metadata) filemeta.set_filemeta(self.item, file_metadata) f.seek(0) rendition_spec = get_renditions_spec() renditions = generate_renditions(f, file_id, [file_id], 'image', content_type, rendition_spec, url_for_media) self.item['renditions'] = renditions archive = get_resource_service('archive') archive.post([self.item])
def on_create(self, docs): """Create corresponding item on file upload.""" for doc in docs: if 'media' not in doc or doc['media'] is None: abort(400, description="No media found") file, content_type, metadata = self.get_file_from_document(doc) inserted = [doc['media']] file_type = content_type.split('/')[0] self._set_metadata(doc) try: doc[ITEM_TYPE] = self.type_av.get(file_type) rendition_spec = get_renditions_spec() renditions = generate_renditions(file, doc['media'], inserted, file_type, content_type, rendition_spec, url_for_media) doc['renditions'] = renditions doc['mimetype'] = content_type set_filemeta(doc, metadata) add_activity('upload', 'uploaded media {{ name }}', 'archive', item=doc, name=doc.get('headline', doc.get('mimetype')), renditions=doc.get('renditions')) except Exception as io: logger.exception(io) for file_id in inserted: delete_file_on_error(doc, file_id) abort(500)
def create(self, docs): """Apply transformation requested in 'edit'""" ids = [] archive = get_resource_service("archive") for doc in docs: # first we get item and requested edit operations item = doc.pop("item", None) if item is None: try: item_id = doc.pop("item_id") except KeyError: raise errors.SuperdeskApiError.badRequestError( "either item or item_id must be specified") else: item_id = item[config.ID_FIELD] if item is None and item_id: item = next(archive.find({"_id": item_id})) edit = doc.pop("edit") # now we retrieve and load current original media rendition = item["renditions"]["original"] media_id = rendition["media"] media = current_app.media.get(media_id) out = im = Image.open(media) # we apply all requested operations on original media for operation, param in edit.items(): try: out = self.transform(out, operation, param) except ValueError: # if the operation can't be applied just ignore it logger.warning( "failed to apply operation: {operation} {param} for media {id}" .format(operation=operation, param=param, id=media_id)) buf = BytesIO() out.save(buf, format=im.format) # we set metadata buf.seek(0) content_type = rendition["mimetype"] ext = os.path.splitext(rendition["href"])[1] filename = str(uuid.uuid4()) + ext # and save transformed media in database media_id = current_app.media.put(buf, filename=filename, content_type=content_type) # now we recreate other renditions based on transformed original media buf.seek(0) renditions = generate_renditions(buf, media_id, [], "image", content_type, get_renditions_spec(), current_app.media.url_for_media) ids.append(item_id) doc["renditions"] = renditions return [ids]
def upload_fixture_image( self, fixture_image_path, verification_stats_path, verification_result_path, headline='test' ): with self.app.app_context(): with open(fixture_image_path, mode='rb') as f: file_name = ntpath.basename(fixture_image_path) file_type = 'image' content_type = '%s/%s' % (file_type, imghdr.what(f)) file_id = app.media.put( f, filename=file_name, content_type=content_type, resource=get_resource_service('ingest').datasource, metadata={} ) inserted = [file_id] renditions = generate_renditions( f, file_id, inserted, file_type, content_type, rendition_config=config.RENDITIONS['picture'], url_for_media=url_for_media ) data = [{ 'headline': headline, 'slugline': 'rebuild', 'renditions': renditions, 'type': 'picture' }] image_id = get_resource_service('ingest').post(data) with open(verification_result_path, 'r') as f: self.expected_verification_results.append(json.load(f)) with open(verification_stats_path, 'r') as f: self.expected_verification_stats.append(json.load(f)) return image_id
def create(self, docs, **kwargs): ids = [] for doc in docs: item = doc.pop('item') orig = item['renditions']['original'] orig_file = get_file(orig, item) no_custom_crops = doc.get('no_custom_crops', False) rendition_spec = get_renditions_spec( no_custom_crops=no_custom_crops) inserted = [] mimetype = item.get('mimetype', orig.get('mimetype', '/')) media_type, content_type = mimetype.split('/') renditions = generate_renditions(orig_file, orig['media'], inserted, media_type, mimetype, rendition_spec, app.media.url_for_media) doc['renditions'] = renditions ids.append(item['_id']) updates = {'renditions': item['renditions']} try: get_resource_service('archive').update(item['_id'], updates, item) except Exception as ex: logger.warning( 'failed to update the renditions for original item in archive' ) return ids
def store_file(self, doc, content, filename, content_type): res = process_file_from_stream(content, filename=filename, content_type=content_type) file_name, content_type, metadata = res cropping_data = self.get_cropping_data(doc) _, out = crop_image(content, filename, cropping_data) metadata['length'] = json.dumps(len(out.getvalue())) try: logger.debug('Going to save media file with %s ' % file_name) out.seek(0) id = app.media.put(out, filename=file_name, content_type=content_type, metadata=metadata) doc['media'] = id doc['mime_type'] = content_type doc['filemeta'] = decode_metadata(metadata) inserted = [doc['media']] file_type = content_type.split('/')[0] rendition_spec = config.RENDITIONS['avatar'] renditions = generate_renditions(out, doc['media'], inserted, file_type, content_type, rendition_spec, url_for_media) doc['renditions'] = renditions except Exception as io: logger.exception(io) for file_id in inserted: delete_file_on_error(doc, file_id) raise SuperdeskError(message='Generating renditions failed')
def setUp(self): super().setUp() dirname = os.path.dirname(os.path.realpath(__file__)) image_path = os.path.normpath( os.path.join(dirname, "fixtures", self.filename)) content_type = mimetypes.guess_type(image_path)[0] guid = utils.generate_guid(type=GUID_TAG) self.item = { "guid": guid, "version": 1, "_id": guid, ITEM_TYPE: CONTENT_TYPE.PICTURE, "mimetype": content_type, "versioncreated": datetime.now(), } with open(image_path, "rb") as f: _, content_type, file_metadata = process_file_from_stream( f, content_type=content_type) f.seek(0) file_id = app.media.put(f, filename=self.filename, content_type=content_type, metadata=file_metadata) filemeta.set_filemeta(self.item, file_metadata) f.seek(0) rendition_spec = get_renditions_spec() renditions = generate_renditions(f, file_id, [file_id], "image", content_type, rendition_spec, url_for_media) self.item["renditions"] = renditions archive = get_resource_service("archive") archive.post([self.item])
def parse_item(self, image_path): filename = os.path.basename(image_path) content_type = mimetypes.guess_type(image_path)[0] guid = utils.generate_guid(type=GUID_TAG) item = {'guid': guid, 'uri': guid, config.VERSION: 1, ITEM_TYPE: CONTENT_TYPE.PICTURE, 'mimetype': content_type, 'versioncreated': utcnow(), } with open(image_path, 'rb') as f: _, content_type, file_metadata = process_file_from_stream(f, content_type=content_type) f.seek(0) file_id = app.media.put(f, filename=filename, content_type=content_type, metadata=file_metadata) filemeta.set_filemeta(item, file_metadata) f.seek(0) metadata = get_meta_iptc(f) f.seek(0) self.parse_meta(item, metadata) rendition_spec = get_renditions_spec(no_custom_crops=True) renditions = generate_renditions(f, file_id, [file_id], 'image', content_type, rendition_spec, url_for_media) item['renditions'] = renditions return item
def test_generate_renditions_custom_crop(self): inserted = [] renditions = get_renditions_spec() with open(IMG_PATH, "rb") as original: generated = generate_renditions( original, "id", inserted, "image", "image/jpeg", renditions, self.app.media.url_for_media ) # thumbnail should keep 4:3 ration self.assertIn("thumbnail", generated) self.assertEqual(160, generated["thumbnail"]["width"]) self.assertEqual(120, generated["thumbnail"]["height"]) # landscape should be cropped to 200x100 self.assertIn("landscape", generated) landscape = generated["landscape"] self.assertEqual(200, landscape["width"]) self.assertEqual(100, landscape["height"]) self.assertEqual(0, landscape["CropLeft"]) self.assertEqual(400, landscape["CropRight"]) self.assertEqual(50, landscape["CropTop"]) self.assertEqual(250, landscape["CropBottom"]) # portrait should be cropped to 150x200 self.assertIn("portrait", generated) portrait = generated["portrait"] self.assertEqual(150, portrait["width"]) self.assertEqual(200, portrait["height"]) self.assertEqual(0, portrait["CropTop"]) self.assertEqual(300, portrait["CropBottom"]) self.assertEqual(87, portrait["CropLeft"]) self.assertEqual(312, portrait["CropRight"])
def find_one_raw(self, resource, _id): # XXX: preview is used here instead of paid download # see SDNTB-15 data = {} url = self._app.config['SCANPIX_SEARCH_URL'] + '/search' data['refPtrs'] = [_id] r = self._request(url, data) doc = r.json()['data'][0] self._parse_doc(doc) url = doc['renditions']['baseImage']['href'] # if MIME type can't be guessed, we default to jpeg mime_type = mimetypes.guess_type(url)[0] or 'image/jpeg' r = self._request(url, data) out = BytesIO(r.content) file_name, content_type, metadata = process_file_from_stream( out, mime_type) logger.debug('Going to save media file with %s ' % file_name) out.seek(0) try: file_id = self._app.media.put(out, filename=file_name, content_type=content_type, metadata=None) except Exception as e: logger.exception(e) raise SuperdeskApiError.internalError('Media saving failed') else: try: inserted = [file_id] doc['mimetype'] = content_type doc['filemeta'] = decode_metadata(metadata) # set the version created to now to bring it to the top of the desk, images can be quite old doc['versioncreated'] = utcnow() file_type = content_type.split('/')[0] rendition_spec = get_renditions_spec() renditions = generate_renditions(out, file_id, inserted, file_type, content_type, rendition_spec, url_for_media, insert_metadata=False) doc['renditions'] = renditions except (IndexError, KeyError, json.JSONDecodeError) as e: logger.exception("Internal error: {}".format(e)) delete_file_on_error(doc, file_id) raise SuperdeskApiError.internalError( 'Generating renditions failed') return doc
def on_create(self, docs): """Create corresponding item on file upload.""" for doc in docs: if 'media' not in doc or doc['media'] is None: abort(400, description="No media found") # check content type of video by python-magic content_type = magic.from_buffer(doc['media'].read(1024), mime=True) doc['media'].seek(0) file_type = content_type.split('/')[0] if file_type == 'video' and app.config.get("VIDEO_SERVER_ENABLE"): if not self.videoEditor.check_video_server(): raise SuperdeskApiError( message="Cannot connect to videoserver", status_code=500) # upload media to video server res, renditions, metadata = self.upload_file_to_video_server( doc) # get thumbnails for timeline bar self.videoEditor.get_timeline_thumbnails(doc.get('media'), 40) else: file, content_type, metadata = self.get_file_from_document(doc) inserted = [doc['media']] # if no_custom_crops is set to False the custom crops are generated automatically on media upload # see (SDESK-4742) rendition_spec = get_renditions_spec( no_custom_crops=app.config.get("NO_CUSTOM_CROPS")) with timer('archive:renditions'): renditions = generate_renditions(file, doc['media'], inserted, file_type, content_type, rendition_spec, url_for_media) try: self._set_metadata(doc) doc[ITEM_TYPE] = self.type_av.get(file_type) doc[ITEM_STATE] = CONTENT_STATE.PROGRESS doc['renditions'] = renditions doc['mimetype'] = content_type set_filemeta(doc, metadata) add_activity('upload', 'uploaded media {{ name }}', 'archive', item=doc, name=doc.get('headline', doc.get('mimetype')), renditions=doc.get('renditions')) except Exception as io: logger.exception(io) for file_id in inserted: delete_file_on_error(doc, file_id) if res: self.videoEditor.delete(res.get('_id')) abort(500)
def on_create(self, docs): """Create corresponding item on file upload.""" for doc in docs: if "media" not in doc or doc["media"] is None: abort(400, description="No media found") # check content type of video by python-magic content_type = app.media._get_mimetype(doc["media"]) doc["media"].seek(0) file_type = content_type.split("/")[0] if file_type == "video" and app.config.get("VIDEO_SERVER_ENABLED"): # upload media to video server res, renditions, metadata = self.upload_file_to_video_server( doc) # get thumbnails for timeline bar self.video_editor.create_timeline_thumbnails( doc.get("media"), 60) else: file, content_type, metadata = self.get_file_from_document(doc) inserted = [doc["media"]] # if no_custom_crops is set to False the custom crops are generated automatically on media upload # see (SDESK-4742) rendition_spec = get_renditions_spec( no_custom_crops=app.config.get("NO_CUSTOM_CROPS")) with timer("archive:renditions"): renditions = generate_renditions(file, doc["media"], inserted, file_type, content_type, rendition_spec, url_for_media) try: self._set_metadata(doc) doc[ITEM_TYPE] = self.type_av.get(file_type) doc[ITEM_STATE] = CONTENT_STATE.PROGRESS doc["renditions"] = renditions doc["mimetype"] = content_type set_filemeta(doc, metadata) add_activity( "upload", "uploaded media {{ name }}", "archive", item=doc, name=doc.get("headline", doc.get("mimetype")), renditions=doc.get("renditions"), ) except Exception as io: logger.exception(io) for file_id in inserted: delete_file_on_error(doc, file_id) if res: self.video_editor.delete(res.get("_id")) abort(500)
def parse_item(self, image_path): filename = os.path.basename(image_path) content_type = mimetypes.guess_type(image_path)[0] guid = utils.generate_guid(type=GUID_TAG) item = { 'guid': guid, config.VERSION: 1, config.ID_FIELD: guid, ITEM_TYPE: CONTENT_TYPE.PICTURE, 'mimetype': content_type, 'versioncreated': datetime.now() } with open(image_path, 'rb') as f: _, content_type, file_metadata = process_file_from_stream( f, content_type=content_type) f.seek(0) file_id = app.media.put(f, filename=filename, content_type=content_type, metadata=file_metadata) filemeta.set_filemeta(item, file_metadata) f.seek(0) metadata = get_meta_iptc(f) f.seek(0) rendition_spec = get_renditions_spec(no_custom_crops=True) renditions = generate_renditions(f, file_id, [file_id], 'image', content_type, rendition_spec, url_for_media) item['renditions'] = renditions try: date_created, time_created = metadata[TAG.DATE_CREATED], metadata[ TAG.TIME_CREATED] except KeyError: pass else: # we format proper ISO 8601 date so we can parse it with dateutil datetime_created = '{}-{}-{}T{}:{}:{}{}{}:{}'.format( date_created[0:4], date_created[4:6], date_created[6:8], time_created[0:2], time_created[2:4], time_created[4:6], time_created[6], time_created[7:9], time_created[9:]) item['firstcreated'] = dateutil.parser.parse(datetime_created) # now we map IPTC metadata to superdesk metadata for source_key, dest_key in IPTC_MAPPING.items(): try: item[dest_key] = metadata[source_key] except KeyError: continue return item
def create(self, docs, **kwargs): ids = [] for doc in docs: item = doc.pop('item') orig = item['renditions']['original'] orig_file = get_file(orig, item) rendition_spec = get_renditions_spec() inserted = [] media_type, content_type = item['mimetype'].split('/') renditions = generate_renditions(orig_file, orig['media'], inserted, media_type, item['mimetype'], rendition_spec, app.media.url_for_media) doc['renditions'] = renditions ids.append(item['_id']) return ids
def test_generate_renditions_base_image(self): inserted = [] renditions = get_renditions_spec() with open(BIG_IMG_PATH, 'rb') as original: generated = generate_renditions(original, 'id', inserted, 'image', 'image/jpeg', renditions, self.app.media.url_for_media) self.assertIn('landscape', generated) landscape = generated['landscape'] self.assertEqual(200, landscape['width']) self.assertEqual(100, landscape['height']) self.assertEqual(0, landscape['CropLeft']) self.assertEqual(1200, landscape['CropRight']) self.assertEqual(500, landscape['CropTop']) self.assertEqual(1100, landscape['CropBottom'])
def create(self, docs, **kwargs): ids = [] for doc in docs: item = doc.pop('item') orig = item['renditions']['original'] orig_file = get_file(orig, item) rendition_spec = get_renditions_spec() inserted = [] mimetype = item.get('mimetype', orig.get('mimetype', '/')) media_type, content_type = mimetype.split('/') renditions = generate_renditions(orig_file, orig['media'], inserted, media_type, mimetype, rendition_spec, app.media.url_for_media) doc['renditions'] = renditions ids.append(item['_id']) return ids
def parse_item(self, image_path): filename = os.path.basename(image_path) content_type = mimetypes.guess_type(image_path)[0] guid = utils.generate_guid(type=GUID_TAG) item = {'guid': guid, config.VERSION: 1, config.ID_FIELD: guid, ITEM_TYPE: CONTENT_TYPE.PICTURE, 'mimetype': content_type, 'versioncreated': datetime.now() } with open(image_path, 'rb') as f: _, content_type, file_metadata = process_file_from_stream(f, content_type=content_type) f.seek(0) file_id = app.media.put(f, filename=filename, content_type=content_type, metadata=file_metadata) filemeta.set_filemeta(item, file_metadata) f.seek(0) metadata = get_meta_iptc(f) f.seek(0) rendition_spec = get_renditions_spec(no_custom_crops=True) renditions = generate_renditions(f, file_id, [file_id], 'image', content_type, rendition_spec, url_for_media) item['renditions'] = renditions try: date_created, time_created = metadata[TAG.DATE_CREATED], metadata[TAG.TIME_CREATED] except KeyError: pass else: # we format proper ISO 8601 date so we can parse it with dateutil datetime_created = '{}-{}-{}T{}:{}:{}{}{}:{}'.format(date_created[0:4], date_created[4:6], date_created[6:8], time_created[0:2], time_created[2:4], time_created[4:6], time_created[6], time_created[7:9], time_created[9:]) item['firstcreated'] = dateutil.parser.parse(datetime_created) # now we map IPTC metadata to superdesk metadata for source_key, dest_key in IPTC_MAPPING.items(): try: item[dest_key] = metadata[source_key] except KeyError: continue return item
def on_create(self, docs): """ Create corresponding item on file upload """ for doc in docs: if 'media' not in doc or doc['media'] is None: abort(400, description="No media found") file, content_type, metadata = self.get_file_from_document(doc) inserted = [doc['media']] file_type = content_type.split('/')[0] try: update_dates_for(doc) generate_unique_id_and_name(doc) doc['guid'] = generate_guid(type=GUID_TAG) doc.setdefault('_id', doc['guid']) doc['type'] = self.type_av.get(file_type) doc[config.VERSION] = 1 doc['versioncreated'] = utcnow() set_item_expiry({}, doc) rendition_spec = config.RENDITIONS['picture'] renditions = generate_renditions(file, doc['media'], inserted, file_type, content_type, rendition_spec, url_for_media) doc['renditions'] = renditions doc['mimetype'] = content_type doc['filemeta'] = metadata if not doc.get('_import', None): set_original_creator(doc) doc.setdefault(config.CONTENT_STATE, 'draft') add_activity('upload', 'uploaded media {{ name }}', item=doc, name=doc.get('headline', doc.get('mimetype')), renditions=doc.get('renditions')) except Exception as io: logger.exception(io) for file_id in inserted: delete_file_on_error(doc, file_id) abort(500) on_create_media_archive()
def test_generate_renditions_base_image(self): inserted = [] renditions = get_renditions_spec() with open(BIG_IMG_PATH, "rb") as original: generated = generate_renditions( original, "id", inserted, "image", "image/jpeg", renditions, self.app.media.url_for_media ) self.assertIn("landscape", generated) landscape = generated["landscape"] self.assertEqual(200, landscape["width"]) self.assertEqual(100, landscape["height"]) self.assertEqual(0, landscape["CropLeft"]) self.assertEqual(1200, landscape["CropRight"]) self.assertEqual(500, landscape["CropTop"]) self.assertEqual(1100, landscape["CropBottom"])
def find_one_raw(self, resource, _id): url = self._app.config['AAP_MM_SEARCH_URL'] + '/Assets/{}'.format(_id) r = self._http.request('GET', url, headers=self._headers) doc = json.loads(r.data.decode('UTF-8')) self._parse_doc(doc) if 'fetch_endpoint' in doc: del doc['fetch_endpoint'] # Only if we have credentials can we download the original if the account has that privilege if 'AAP_MM_USER' in self._app.config and 'AAP_MM_PASSWORD' in self._app.config \ and self._app.config['AAP_MM_USER'] is not None: url = self._app.config[ 'AAP_MM_SEARCH_URL'] + '/Assets/{}/Original/download'.format( _id) else: url = doc['renditions']['original']['href'] r = self._http.request('GET', url, headers=self._headers) out = BytesIO(r.data) file_name, content_type, metadata = process_file_from_stream( out, 'image/jpeg') try: logger.debug('Going to save media file with %s ' % file_name) out.seek(0) file_id = self._app.media.put(out, filename=file_name, content_type=content_type, metadata=metadata) doc['mimetype'] = content_type doc['filemeta'] = decode_metadata(metadata) # set the version created to now to bring it to the top of the desk, images can be quite old doc['versioncreated'] = utcnow() inserted = [file_id] file_type = content_type.split('/')[0] rendition_spec = self._app.config['RENDITIONS']['picture'] renditions = generate_renditions(out, file_id, inserted, file_type, content_type, rendition_spec, self.url_for_media) doc['renditions'] = renditions except Exception as io: logger.exception(io) for file_id in inserted: delete_file_on_error(doc, file_id) return doc
def create(self, docs): """Apply transformation requested in "edit" an item with updated rendition will be returned. All created files are temporary, meaning they will be deleted after a delay or a cleaning. """ try: item = request.json['item'] except KeyError: try: item_id = request.json['item_id'] except KeyError: raise errors.SuperdeskApiError.badRequestError( 'either item or item_id must be specified') item = next(get_resource_service('archive').find({'_id': item_id})) edit = request.json['edit'] rendition = item['renditions']['original'] media_id = rendition['media'] media = current_app.media.get(media_id) out = im = Image.open(media) for operation, param in edit.items(): try: out = self.transform(out, operation, param) except ValueError as e: raise errors.SuperdeskApiError.badRequestError( 'invalid edit instructions: {msg}'.format(msg=e)) buf = BytesIO() out.save(buf, format=im.format) buf.seek(0) content_type = rendition['mimetype'] ext = os.path.splitext(rendition['href'])[1] filename = str(uuid.uuid4()) + ext media_id = current_app.media.put(buf, filename=filename, content_type=content_type, folder='temp') buf.seek(0) renditions = generate_renditions(buf, media_id, [], 'image', content_type, get_renditions_spec(), current_app.media.url_for_media, temporary=True) item['renditions'] = renditions docs[:] = [item] return [item['_id']]
def on_create(self, docs): """ Create corresponding item on file upload """ for doc in docs: if 'media' not in doc or doc['media'] is None: abort(400, description="No media found") file, content_type, metadata = self.get_file_from_document(doc) inserted = [doc['media']] file_type = content_type.split('/')[0] try: update_dates_for(doc) generate_unique_id_and_name(doc) doc['guid'] = generate_guid(type=GUID_TAG) doc.setdefault('_id', doc['guid']) doc['type'] = self.type_av.get(file_type) doc[config.VERSION] = 1 doc['versioncreated'] = utcnow() set_item_expiry({}, doc) rendition_spec = config.RENDITIONS['picture'] renditions = generate_renditions(file, doc['media'], inserted, file_type, content_type, rendition_spec, url_for_media) doc['renditions'] = renditions doc['mimetype'] = content_type doc['filemeta'] = metadata if not doc.get('_import', None): set_original_creator(doc) doc.setdefault(config.CONTENT_STATE, 'draft') if not doc.get('ingest_provider'): doc['source'] = DEFAULT_SOURCE_VALUE_FOR_MANUAL_ARTICLES add_activity('upload', 'uploaded media {{ name }}', 'archive', item=doc, name=doc.get('headline', doc.get('mimetype')), renditions=doc.get('renditions')) except Exception as io: logger.exception(io) for file_id in inserted: delete_file_on_error(doc, file_id) abort(500)
def update_renditions(item, href): inserted = [] try: content, filename, content_type = download_file_from_url(href) file_type, ext = content_type.split('/') metadata = process_file(content, file_type) file_guid = app.media.put(content, filename, content_type, metadata) inserted.append(file_guid) rendition_spec = app.config.get('RENDITIONS', {}).get('picture', {}) renditions = generate_renditions(content, file_guid, inserted, file_type, content_type, rendition_spec, url_for_media) item['renditions'] = renditions item['mimetype'] = content_type item['filemeta'] = metadata except Exception: for file_id in inserted: app.media.delete(file_id) raise
def find_one_raw(self, resource, _id): if self._headers is None: self.__set_auth_cookie(self._app) url = self._app.config['AAP_MM_SEARCH_URL'] + '/Assets/{}'.format(_id) r = self._http.request('GET', url, headers=self._headers) doc = json.loads(r.data.decode('UTF-8')) self._parse_doc(doc) if 'fetch_endpoint' in doc: del doc['fetch_endpoint'] # Only if we have credentials can we download the original if the account has that privilege if 'AAP_MM_USER' in self._app.config and 'AAP_MM_PASSWORD' in self._app.config \ and self._app.config['AAP_MM_USER'] is not None: url = self._app.config['AAP_MM_SEARCH_URL'] + '/Assets/{}/Original/download'.format(_id) else: url = doc['renditions']['original']['href'] r = self._http.request('GET', url, headers=self._headers) out = BytesIO(r.data) file_name, content_type, metadata = process_file_from_stream(out, 'image/jpeg') try: logger.debug('Going to save media file with %s ' % file_name) out.seek(0) file_id = self._app.media.put(out, filename=file_name, content_type=content_type, metadata=metadata) doc['mimetype'] = content_type doc['filemeta'] = decode_metadata(metadata) # set the version created to now to bring it to the top of the desk, images can be quite old doc['versioncreated'] = utcnow() inserted = [file_id] file_type = content_type.split('/')[0] rendition_spec = self._app.config['RENDITIONS']['picture'] renditions = generate_renditions(out, file_id, inserted, file_type, content_type, rendition_spec, self.url_for_media) doc['renditions'] = renditions except Exception as io: logger.exception(io) for file_id in inserted: delete_file_on_error(doc, file_id) return doc
def on_create(self, docs): """ Create corresponding item on file upload """ for doc in docs: if 'media' not in doc or doc['media'] is None: abort(400, description="No media found") file, content_type, metadata = self.get_file_from_document(doc) inserted = [doc['media']] file_type = content_type.split('/')[0] self._set_metadata(doc) try: doc[ITEM_TYPE] = self.type_av.get(file_type) # renditions required by superdesk rendition_spec = config.RENDITIONS['picture'] # load custom crop sizes custom_crops = get_resource_service('vocabularies').find_one( req=None, _id='crop_sizes') if custom_crops: for crop in custom_crops.get('items'): # complete list of wanted renditions rendition_spec[crop['name']] = crop renditions = generate_renditions(file, doc['media'], inserted, file_type, content_type, rendition_spec, url_for_media) doc['renditions'] = renditions doc['mimetype'] = content_type doc['filemeta'] = metadata add_activity('upload', 'uploaded media {{ name }}', 'archive', item=doc, name=doc.get('headline', doc.get('mimetype')), renditions=doc.get('renditions')) except Exception as io: logger.exception(io) for file_id in inserted: delete_file_on_error(doc, file_id) abort(500)
def update_renditions(item, href, old_item): """Update renditions for an item. If the old_item has renditions uploaded in to media then the old rendition details are assigned to the item, this avoids repeatedly downloading the same image and leaving the media entries orphaned. If there is no old_item the original is downloaded and renditions are generated. :param item: parsed item from source :param href: reference to original :param old_item: the item that we have already ingested, if it exists :return: item with renditions """ inserted = [] try: # If there is an existing set of renditions we keep those if old_item: media = old_item.get('renditions', {}).get('original', {}).get('media', {}) if media: item['renditions'] = old_item['renditions'] item['mimetype'] = old_item.get('mimetype') item['filemeta'] = old_item.get('filemeta') item['filemeta_json'] = old_item.get('filemeta_json') return content, filename, content_type = download_file_from_url(href) file_type, ext = content_type.split('/') metadata = process_file(content, file_type) file_guid = app.media.put(content, filename, content_type, metadata) inserted.append(file_guid) rendition_spec = get_renditions_spec() renditions = generate_renditions(content, file_guid, inserted, file_type, content_type, rendition_spec, url_for_media) item['renditions'] = renditions item['mimetype'] = content_type set_filemeta(item, metadata) except Exception as e: logger.exception(e) for file_id in inserted: app.media.delete(file_id) raise
def update_renditions(item, href): inserted = [] try: content, filename, content_type = download_file_from_url(href) file_type, ext = content_type.split('/') metadata = process_file(content, file_type) file_guid = app.media.put(content, filename, content_type, metadata) inserted.append(file_guid) rendition_spec = app.config.get('RENDITIONS', {}).get('picture', {}) renditions = generate_renditions(content, file_guid, inserted, file_type, content_type, rendition_spec, url_for_media) item['renditions'] = renditions item['mimetype'] = content_type item['filemeta'] = metadata except Exception: for file_id in inserted: app.media.delete(file_id) raise
def on_create(self, docs): """Create corresponding item on file upload.""" for doc in docs: if 'media' not in doc or doc['media'] is None: abort(400, description="No media found") file, content_type, metadata = self.get_file_from_document(doc) inserted = [doc['media']] file_type = content_type.split('/')[0] self._set_metadata(doc) try: doc[ITEM_TYPE] = self.type_av.get(file_type) doc[ITEM_STATE] = CONTENT_STATE.PROGRESS # if no_custom_crops is set to False the custom crops are generated automatically on media upload # see (SDESK-4742) rendition_spec = get_renditions_spec( no_custom_crops=app.config.get("NO_CUSTOM_CROPS")) with timer('archive:renditions'): renditions = generate_renditions(file, doc['media'], inserted, file_type, content_type, rendition_spec, url_for_media) doc['renditions'] = renditions doc['mimetype'] = content_type set_filemeta(doc, metadata) add_activity('upload', 'uploaded media {{ name }}', 'archive', item=doc, name=doc.get('headline', doc.get('mimetype')), renditions=doc.get('renditions')) except Exception as io: logger.exception(io) for file_id in inserted: delete_file_on_error(doc, file_id) abort(500)
def create(self, docs, **kwargs): ids = [] for doc in docs: item = doc.pop("item") orig = item["renditions"]["original"] orig_file = get_file(orig, item) no_custom_crops = doc.get("no_custom_crops", False) rendition_spec = get_renditions_spec( no_custom_crops=no_custom_crops) inserted = [] mimetype = item.get("mimetype", orig.get("mimetype", "/")) media_type, content_type = mimetype.split("/") renditions = generate_renditions(orig_file, orig["media"], inserted, media_type, mimetype, rendition_spec, app.media.url_for_media) doc["renditions"] = renditions ids.append(item["_id"]) return ids
def update_renditions(item, href, old_item): """ If the old_item has renditions uploaded in to media then the old rendition details are assigned to the item, this avoids repeatedly downloading the same image and leaving the media entries orphaned. If there is no old_item the original is downloaded and renditions are generated. :param item: parsed item from source :param href: reference to original :param old_item: the item that we have already injested, if it exists :return: item with renditions """ inserted = [] try: # If there is an existing set of renditions we keep those if old_item: media = old_item.get('renditions', {}).get('original', {}).get('media', {}) if media: item['renditions'] = old_item['renditions'] item['mimetype'] = old_item.get('mimetype') item['filemeta'] = old_item.get('filemeta') logger.info("Reuters image not updated for GUID:{}".format(item[GUID_FIELD])) return content, filename, content_type = download_file_from_url(href) file_type, ext = content_type.split('/') metadata = process_file(content, file_type) file_guid = app.media.put(content, filename, content_type, metadata) inserted.append(file_guid) rendition_spec = app.config.get('RENDITIONS', {}).get('picture', {}) renditions = generate_renditions(content, file_guid, inserted, file_type, content_type, rendition_spec, url_for_media) item['renditions'] = renditions item['mimetype'] = content_type item['filemeta'] = metadata except Exception: for file_id in inserted: app.media.delete(file_id) raise
def create(self, docs): """Apply transformation requested in 'edit'""" ids = [] archive = get_resource_service('archive') for idx, doc in enumerate(docs): # first we get item and requested edit operations try: item = doc.pop('item') except KeyError: try: item_id = doc.pop('item_id') except KeyError: raise errors.SuperdeskApiError.badRequestError( 'either item or item_id must be specified') else: item_id = item[config.ID_FIELD] item = next(archive.find({'_id': item_id})) edit = doc.pop('edit') # now we retrieve and load current original media rendition = item['renditions']['original'] media_id = rendition['media'] media = current_app.media.get(media_id) out = im = Image.open(media) # we apply all requested operations on original media for operation, param in edit.items(): try: out = self.transform(out, operation, param) except ValueError: # if the operation can't be applied just ignore it logger.warning( 'failed to apply operation: {operation} {param} for media {id}' .format(operation=operation, param=param, id=media_id)) buf = BytesIO() out.save(buf, format=im.format) # we set metadata buf.seek(0) content_type = rendition['mimetype'] ext = os.path.splitext(rendition['href'])[1] filename = str(uuid.uuid4()) + ext # and save transformed media in database media_id = current_app.media.put(buf, filename=filename, content_type=content_type) # now we recreate other renditions based on transformed original media buf.seek(0) renditions = generate_renditions(buf, media_id, [], 'image', content_type, get_renditions_spec(), current_app.media.url_for_media) # we update item in db, and the item we'll return to client # we keep old renditions in GridFS for history references updates = {'renditions': renditions} ids.append(item_id) archive.update(item_id, updates, item) item.update(updates) docs[idx] = item return [ids]
def create(self, docs): """Apply transformation requested in 'edit'""" ids = [] archive = get_resource_service('archive') for idx, doc in enumerate(docs): # first we get item and requested edit operations try: item = doc.pop('item') except KeyError: try: item_id = doc.pop('item_id') except KeyError: raise errors.SuperdeskApiError.badRequestError('either item or item_id must be specified') else: item_id = item[config.ID_FIELD] item = next(archive.find({'_id': item_id})) edit = doc.pop('edit') # new we retrieve and loag current original media rendition = item['renditions']['original'] media_id = rendition['media'] media = current_app.media.get(media_id) out = im = Image.open(media) # we apply all requested operations on original media for operation, param in edit.items(): try: out = self.transform(out, operation, param) except ValueError as e: raise errors.SuperdeskApiError.badRequestError('invalid edit instructions: {msg}'.format(msg=e)) buf = BytesIO() out.save(buf, format=im.format) # we set metadata buf.seek(0) content_type = rendition['mimetype'] ext = os.path.splitext(rendition['href'])[1] filename = str(uuid.uuid4()) + ext # and save transformed media in database media_id = current_app.media.put(buf, filename=filename, content_type=content_type, folder='temp') # now we recreate other renditions based on transformed original media buf.seek(0) # we keep old renditions to later delete old files renditions = generate_renditions(buf, media_id, [], 'image', content_type, get_renditions_spec(), current_app.media.url_for_media, temporary=True) # we update item in db, and the item we'll return to client updates = {'renditions': renditions} ids.append(item_id) archive.update(item_id, updates, item) # we keep old renditions to later delete old files item.update(updates) docs[idx] = item return [ids]
def find_one_raw(self, resource, _id): if self._headers is None: self.__set_auth_cookie(self._app) url = self._app.config["AAP_MM_SEARCH_URL"] + "/Assets/{}".format(_id) r = self._http.request("GET", url, headers=self._headers) doc = json.loads(r.data.decode("UTF-8")) self._parse_doc(doc) if "fetch_endpoint" in doc: del doc["fetch_endpoint"] # Only if we have credentials can we download the original if the account has that privilege if self._username is not None and self._password is not None: resolutions = self._get_resolutions(_id) if doc["type"] == "picture": if any(i["Name"] == "Original" for i in resolutions["Image"]): url = self._app.config["AAP_MM_SEARCH_URL"] + "/Assets/{}/Original/download".format(_id) mime_type = "image/jpeg" source_ref = {"href": url, "mimetype": mime_type} else: raise FileNotFoundError elif doc["type"] == "video": if any(v["Name"] == "Ipod" for v in resolutions["Video"]): url = self._app.config["AAP_MM_SEARCH_URL"] + "/Assets/{}/Ipod/download".format(_id) mime_type = doc.get("renditions").get("original").get("mimetype") else: raise FileNotFoundError if any(v["Name"] == "Video" for v in resolutions["Video"]): source_ref = { "href": self._app.config["AAP_MM_SEARCH_URL"] + "/Assets/{}/Video/download".format(_id), "mimetype": "video/quicktime", } else: raise FileNotFoundError else: raise NotImplementedError else: if doc["type"] == "video": mime_type = doc.get("renditions").get("original").get("mimetype") else: mime_type = "image/jpeg" url = doc["renditions"]["original"]["href"] source_ref = {"href": url, "mimetype": mime_type} r = self._http.request("GET", url, headers=self._headers) out = BytesIO(r.data) file_name, content_type, metadata = process_file_from_stream(out, mime_type) try: logger.debug("Going to save media file with %s " % file_name) out.seek(0) file_id = self._app.media.put(out, filename=file_name, content_type=content_type, metadata=metadata) doc["mimetype"] = content_type doc["filemeta"] = decode_metadata(metadata) # set the version created to now to bring it to the top of the desk, images can be quite old doc["versioncreated"] = utcnow() inserted = [file_id] file_type = content_type.split("/")[0] rendition_spec = self._app.config["RENDITIONS"]["picture"] renditions = generate_renditions( out, file_id, inserted, file_type, content_type, rendition_spec, self.url_for_media ) doc["renditions"] = renditions doc["renditions"]["original_source"] = source_ref except Exception as io: logger.exception(io) for file_id in inserted: delete_file_on_error(doc, file_id) return doc
def create(self, docs): """Apply transformation requested in 'edit'""" ids = [] archive = get_resource_service('archive') for idx, doc in enumerate(docs): # first we get item and requested edit operations try: item = doc.pop('item') except KeyError: try: item_id = doc.pop('item_id') except KeyError: raise errors.SuperdeskApiError.badRequestError('either item or item_id must be specified') else: item_id = item[config.ID_FIELD] item = next(archive.find({'_id': item_id})) edit = doc.pop('edit') # now we retrieve and load current original media rendition = item['renditions']['original'] media_id = rendition['media'] media = current_app.media.get(media_id) out = im = Image.open(media) # we apply all requested operations on original media for operation, param in edit.items(): try: out = self.transform(out, operation, param) except ValueError: # if the operation can't be applied just ignore it logger.warning('failed to apply operation: {operation} {param} for media {id}'.format( operation=operation, param=param, id=media_id)) buf = BytesIO() out.save(buf, format=im.format) # we set metadata buf.seek(0) content_type = rendition['mimetype'] ext = os.path.splitext(rendition['href'])[1] filename = str(uuid.uuid4()) + ext # and save transformed media in database media_id = current_app.media.put(buf, filename=filename, content_type=content_type) # now we recreate other renditions based on transformed original media buf.seek(0) renditions = generate_renditions(buf, media_id, [], 'image', content_type, get_renditions_spec(), current_app.media.url_for_media) # we update item in db, and the item we'll return to client # we keep old renditions in GridFS for history references updates = {'renditions': renditions} ids.append(item_id) archive.update(item_id, updates, item) item.update(updates) docs[idx] = item return [ids]
def find_one_raw(self, resource, _id): if self._headers is None: self.__set_auth_cookie(self._app) url = self._app.config['AAP_MM_SEARCH_URL'] + '/Assets/{}'.format(_id) r = self._http.request('GET', url, headers=self._headers) doc = json.loads(r.data.decode('UTF-8')) self._parse_doc(doc) if 'fetch_endpoint' in doc: del doc['fetch_endpoint'] # Only if we have credentials can we download the original if the account has that privilege if self._username is not None and self._password is not None: resolutions = self._get_resolutions(_id) if doc[ITEM_TYPE] == CONTENT_TYPE.PICTURE: if any(i['Name'] == 'Original' for i in resolutions['Image']): url = self._app.config['AAP_MM_SEARCH_URL'] + '/Assets/{}/Original/download'.format(_id) mime_type = 'image/jpeg' else: raise FileNotFoundError elif doc[ITEM_TYPE] == CONTENT_TYPE.VIDEO: if any(v['Name'] == 'Ipod' for v in resolutions['Video']): url = self._app.config['AAP_MM_SEARCH_URL'] + '/Assets/{}/Ipod/download'.format(_id) mime_type = doc.get('renditions').get('original').get('mimetype') else: raise FileNotFoundError else: raise NotImplementedError else: if doc[ITEM_TYPE] == CONTENT_TYPE.VIDEO: mime_type = doc.get('renditions').get('original').get('mimetype') else: mime_type = 'image/jpeg' url = doc['renditions']['original']['href'] r = self._http.request('GET', url, headers=self._headers) out = BytesIO(r.data) file_name, content_type, metadata = process_file_from_stream(out, mime_type) inserted = [] try: logger.debug('Going to save media file with %s ' % file_name) out.seek(0) file_id = self._app.media.put(out, filename=file_name, content_type=content_type, metadata=None) doc['mimetype'] = content_type doc['filemeta'] = decode_metadata(metadata) # set the version created to now to bring it to the top of the desk, images can be quite old doc['versioncreated'] = utcnow() inserted = [file_id] file_type = content_type.split('/')[0] rendition_spec = self._app.config['RENDITIONS']['picture'] renditions = generate_renditions(out, file_id, inserted, file_type, content_type, rendition_spec, self.url_for_media, insert_metadata=False) doc['renditions'] = renditions except Exception as io: logger.exception(io) for file_id in inserted: delete_file_on_error(doc, file_id) raise SuperdeskApiError.internalError('Generating renditions failed') return doc
def find_one_raw(self, resource, _id): if self._headers is None: self.__set_auth_cookie(self._app) url = self._app.config['AAP_MM_SEARCH_URL'] + '/Assets/{}'.format(_id) r = self._http.request('GET', url, headers=self._headers) doc = json.loads(r.data.decode('UTF-8')) self._parse_doc(doc) if 'fetch_endpoint' in doc: del doc['fetch_endpoint'] # Only if we have credentials can we download the original if the account has that privilege if self._username is not None and self._password is not None: resolutions = self._get_resolutions(_id) if doc[ITEM_TYPE] == CONTENT_TYPE.PICTURE: if any(i['Name'] == 'Original' for i in resolutions['Image']): url = self._app.config[ 'AAP_MM_SEARCH_URL'] + '/Assets/{}/Original/download'.format( _id) mime_type = 'image/jpeg' else: raise FileNotFoundError elif doc[ITEM_TYPE] == CONTENT_TYPE.VIDEO: if any(v['Name'] == 'Ipod' for v in resolutions['Video']): url = self._app.config[ 'AAP_MM_SEARCH_URL'] + '/Assets/{}/Ipod/download'.format( _id) mime_type = doc.get('renditions').get('original').get( 'mimetype') else: raise FileNotFoundError else: raise NotImplementedError else: if doc[ITEM_TYPE] == CONTENT_TYPE.VIDEO: mime_type = doc.get('renditions').get('original').get( 'mimetype') else: mime_type = 'image/jpeg' url = doc['renditions']['original']['href'] r = self._http.request('GET', url, headers=self._headers) out = BytesIO(r.data) file_name, content_type, metadata = process_file_from_stream( out, mime_type) inserted = [] try: logger.debug('Going to save media file with %s ' % file_name) out.seek(0) file_id = self._app.media.put(out, filename=file_name, content_type=content_type, metadata=None) doc['mimetype'] = content_type doc['filemeta'] = decode_metadata(metadata) # set the version created to now to bring it to the top of the desk, images can be quite old doc['versioncreated'] = utcnow() inserted = [file_id] file_type = content_type.split('/')[0] rendition_spec = self._app.config['RENDITIONS']['picture'] renditions = generate_renditions(out, file_id, inserted, file_type, content_type, rendition_spec, self.url_for_media, insert_metadata=False) doc['renditions'] = renditions except Exception as io: logger.exception(io) for file_id in inserted: delete_file_on_error(doc, file_id) raise SuperdeskApiError.internalError( 'Generating renditions failed') return doc