def image_upload(request): # Used for content nodes if request.method != 'POST': return HttpResponseBadRequest( "Only POST requests are allowed on this endpoint.") fobj = request.FILES.values()[0] name, ext = os.path.splitext( fobj._name) # gets file extension without leading period checksum = get_hash(DjFile(fobj)) request.user.check_space(fobj._size, checksum) file_object = File(contentnode_id=request.META.get('HTTP_NODE'), original_filename=name, preset_id=request.META.get('HTTP_PRESET'), file_on_disk=DjFile(request.FILES.values()[0]), file_format_id=ext[1:].lower(), uploaded_by=request.user) file_object.save() return HttpResponse( json.dumps({ "success": True, "file": JSONRenderer().render(FileSerializer(file_object).data), "path": generate_storage_url(str(file_object)), "encoding": get_thumbnail_encoding(str(file_object)), }))
def image_upload(request): # Used for content nodes if request.method != 'POST': return HttpResponseBadRequest("Only POST requests are allowed on this endpoint.") fobj = request.FILES.values()[0] name, ext = os.path.splitext(fobj._name) # gets file extension without leading period checksum = get_hash(DjFile(fobj)) request.user.check_space(fobj._size, checksum) file_object = File( contentnode_id=request.META.get('HTTP_NODE'), original_filename=name, preset_id=request.META.get('HTTP_PRESET'), file_on_disk=DjFile(request.FILES.values()[0]), file_format_id=ext[1:].lower(), uploaded_by=request.user ) file_object.save() return HttpResponse(json.dumps({ "success": True, "file": JSONRenderer().render(FileSerializer(file_object).data), "path": generate_storage_url(str(file_object)), "encoding": get_thumbnail_encoding(str(file_object)), }))
def generate_thumbnail(request, contentnode_id): logging.debug("Entering the generate_thumbnail endpoint") if request.method != 'POST': return HttpResponseBadRequest( "Only POST requests are allowed on this endpoint.") node = ContentNode.objects.get(pk=contentnode_id) thumbnail_object = generate_thumbnail_from_node(node) try: request.user.check_space(thumbnail_object.file_size, thumbnail_object.checksum) except Exception as e: if thumbnail_object: thumbnail_object.delete() raise e return HttpResponse( json.dumps({ "success": True, "file": JSONRenderer().render(FileSerializer(thumbnail_object).data), "path": generate_storage_url(str(thumbnail_object)), "encoding": get_thumbnail_encoding(str(thumbnail_object)), }))
def map_files_to_node(user, node, data): """ Generate files that reference the content node. """ if settings.DEBUG: # assert that our parameters match expected values assert isinstance(user, User) assert isinstance(node, ContentNode) assert isinstance(data, list) # filter out file that are empty valid_data = filter_out_nones(data) for file_data in valid_data: filename = file_data["filename"] checksum, ext1 = os.path.splitext(filename) ext = ext1.lstrip(".") # Determine a preset if none is given kind_preset = FormatPreset.get_preset(file_data["preset"]) or FormatPreset.guess_format_preset(filename) file_path = generate_object_storage_name(checksum, filename) storage = default_storage if not storage.exists(file_path): raise IOError('{} not found'.format(file_path)) try: if file_data.get('language'): # TODO: Remove DB call per file? file_data['language'] = Language.objects.get(pk=file_data['language']) except ObjectDoesNotExist: invalid_lang = file_data.get('language') logging.warning("file_data with language {} does not exist.".format(invalid_lang)) return ValidationError("file_data given was invalid; expected string, got {}".format(invalid_lang)) resource_obj = File( checksum=checksum, contentnode=node, file_format_id=ext, original_filename=file_data.get('original_filename') or 'file', source_url=file_data.get('source_url'), file_size=file_data['size'], preset=kind_preset, language_id=file_data.get('language'), uploaded_by=user, ) resource_obj.file_on_disk.name = file_path resource_obj.save() # Handle thumbnail if resource_obj.preset and resource_obj.preset.thumbnail: node.thumbnail_encoding = json.dumps({ 'base64': get_thumbnail_encoding(str(resource_obj)), 'points': [], 'zoom': 0 }) node.save()
def map_files_to_node(user, node, data): """ Generate files that reference the content node. """ if settings.DEBUG: # assert that our parameters match expected values assert isinstance(user, User) assert isinstance(node, ContentNode) assert isinstance(data, list) # filter out file that are empty valid_data = filter_out_nones(data) for file_data in valid_data: filename = file_data["filename"] checksum, ext1 = os.path.splitext(filename) ext = ext1.lstrip(".") # Determine a preset if none is given kind_preset = FormatPreset.get_preset(file_data["preset"]) or FormatPreset.guess_format_preset(filename) file_path = generate_object_storage_name(checksum, filename) storage = default_storage if not storage.exists(file_path): raise IOError('{} not found'.format(file_path)) try: if file_data.get('language'): # TODO: Remove DB call per file? file_data['language'] = Language.objects.get(pk=file_data['language']) except ObjectDoesNotExist: invalid_lang = file_data.get('language') logging.warning("file_data with language {} does not exist.".format(invalid_lang)) return ValidationError("file_data given was invalid; expected string, got {}".format(invalid_lang)) resource_obj = File( checksum=checksum, contentnode=node, file_format_id=ext, original_filename=file_data.get('original_filename') or 'file', source_url=file_data.get('source_url'), file_size=file_data['size'], preset=kind_preset, language_id=file_data.get('language'), uploaded_by=user, ) resource_obj.file_on_disk.name = file_path resource_obj.save() # Handle thumbnail if resource_obj.preset and resource_obj.preset.thumbnail: node.thumbnail_encoding = json.dumps({ 'base64': get_thumbnail_encoding(str(resource_obj)), 'points': [], 'zoom': 0 }) node.save()
def encode_static_base64(value, dimension=None): try: if value.startswith(settings.STATIC_URL): value = os.path.basename(value) filepath = os.path.join(settings.STATIC_ROOT, 'img', value) if dimension: return get_thumbnail_encoding(filepath, dimension=int(dimension)) with open(filepath, 'rb') as image_file: _, ext = os.path.splitext(value) return "data:image/{};base64,{}".format(ext[1:], base64.b64encode(image_file.read())) except IOError: logging.warning("Could not find {}".format(value)) return DEFAULT_ENCODING
def encode_static_base64(value, dimension=None): try: if value.startswith(settings.STATIC_URL): value = os.path.basename(value) filepath = os.path.join(settings.STATIC_ROOT, 'img', value) if dimension: return get_thumbnail_encoding(filepath, dimension=int(dimension)) with open(filepath, 'rb') as image_file: _, ext = os.path.splitext(value) return "data:image/{};base64,{}".format( ext[1:], base64.b64encode(image_file.read())) except IOError: logging.warning("Could not find {}".format(value)) return DEFAULT_ENCODING
def encode_base64(value, dimension=THUMBNAIL_DIMENSION): if value.startswith("data:image"): return value try: return get_thumbnail_encoding(value, dimension=dimension) except IOError: try: filepath = os.path.join(settings.STATIC_ROOT, 'img', 'kolibri_placeholder.png') with open(filepath, 'rb') as image_file: _, ext = os.path.splitext(value) return "data:image/{};base64,{}".format(ext[1:], base64.b64encode(image_file.read())) except IOError: logging.warning("Could not find {}".format(value)) return DEFAULT_ENCODING
def convert_channel_thumbnail(channel): """ encode_thumbnail: gets base64 encoding of thumbnail Args: thumbnail (str): file path or url to channel's thumbnail Returns: base64 encoding of thumbnail """ if not channel.thumbnail or channel.thumbnail == '' or 'static' in channel.thumbnail: return "" if channel.thumbnail_encoding: try: thumbnail_data = channel.thumbnail_encoding if thumbnail_data.get("base64"): return thumbnail_data["base64"] except ValueError: logging.error("ERROR: channel thumbnail is not in correct format ({}: {})".format(channel.id, channel.thumbnail_encoding)) return get_thumbnail_encoding(channel.thumbnail)
def convert_channel_thumbnail(channel): """ encode_thumbnail: gets base64 encoding of thumbnail Args: thumbnail (str): file path or url to channel's thumbnail Returns: base64 encoding of thumbnail """ if not channel.thumbnail or channel.thumbnail == '' or 'static' in channel.thumbnail: return "" if channel.thumbnail_encoding: try: thumbnail_data = channel.thumbnail_encoding if thumbnail_data.get("base64"): return thumbnail_data["base64"] except ValueError: logging.error("ERROR: channel thumbnail is not in correct format ({}: {})".format(channel.id, channel.thumbnail_encoding)) return get_thumbnail_encoding(channel.thumbnail)
def encode_base64(value, dimension=THUMBNAIL_DIMENSION): if value.startswith("data:image"): return value try: return get_thumbnail_encoding(value, dimension=dimension) except IOError: try: filepath = os.path.join(settings.STATIC_ROOT, 'img', 'kolibri_placeholder.png') with open(filepath, 'rb') as image_file: _, ext = os.path.splitext(value) return "data:image/{};base64,{}".format( ext[1:], base64.b64encode(image_file.read())) except IOError: logging.warning("Could not find {}".format(value)) return DEFAULT_ENCODING
def thumbnail_upload(request): # Used for channels if request.method != 'POST': return HttpResponseBadRequest("Only POST requests are allowed on this endpoint.") fobj = request.FILES.values()[0] checksum = get_hash(DjFile(fobj)) request.user.check_space(fobj._size, checksum) formatted_filename = write_file_to_storage(fobj) return HttpResponse(json.dumps({ "success": True, "formatted_filename": formatted_filename, "file": None, "path": generate_storage_url(formatted_filename), "encoding": get_thumbnail_encoding(formatted_filename), }))
def thumbnail_upload(request): # Used for channels if request.method != 'POST': return HttpResponseBadRequest("Only POST requests are allowed on this endpoint.") fobj = request.FILES.values()[0] checksum = get_hash(DjFile(fobj)) request.user.check_space(fobj._size, checksum) formatted_filename = write_file_to_storage(fobj) return HttpResponse(json.dumps({ "success": True, "formatted_filename": formatted_filename, "file": None, "path": generate_storage_url(formatted_filename), "encoding": get_thumbnail_encoding(formatted_filename), }))
def create_associated_thumbnail(ccnode, ccfilemodel): """ Gets the appropriate thumbnail for export (uses or generates a base64 encoding) Args: ccnode (<ContentNode>): node to derive thumbnail from (if encoding is provided) ccfilemodel (<File>): file to get thumbnail from if no encoding is available Returns <File> model of encoded, resized thumbnail """ encoding = None try: encoding = ccnode.thumbnail_encoding and load_json_string( ccnode.thumbnail_encoding).get('base64') except ValueError: logging.error( "ERROR: node thumbnail is not in correct format ({}: {})".format( ccnode.id, ccnode.thumbnail_encoding)) return # Save the encoding if it doesn't already have an encoding if not encoding: try: encoding = get_thumbnail_encoding(str(ccfilemodel)) except IOError: # ImageMagick may raise an IOError if the file is not a thumbnail. Catch that then just return early. logging.error( "ERROR: cannot identify the thumbnail ({}: {})".format( ccnode.id, ccnode.thumbnail_encoding)) return ccnode.thumbnail_encoding = json.dumps({ "base64": encoding, "points": [], "zoom": 0, }) ccnode.save() return create_thumbnail_from_base64( encoding, uploaded_by=ccfilemodel.uploaded_by, file_format_id=ccfilemodel.file_format_id, preset_id=ccfilemodel.preset_id)
def generate_thumbnail(request, contentnode_id): logging.debug("Entering the generate_thumbnail endpoint") if request.method != 'POST': return HttpResponseBadRequest("Only POST requests are allowed on this endpoint.") node = ContentNode.objects.get(pk=contentnode_id) thumbnail_object = generate_thumbnail_from_node(node) try: request.user.check_space(thumbnail_object.file_size, thumbnail_object.checksum) except Exception as e: if thumbnail_object: thumbnail_object.delete() raise e return HttpResponse(json.dumps({ "success": True, "file": JSONRenderer().render(FileSerializer(thumbnail_object).data), "path": generate_storage_url(str(thumbnail_object)), "encoding": get_thumbnail_encoding(str(thumbnail_object)), }))
def create_associated_thumbnail(ccnode, ccfilemodel): """ Gets the appropriate thumbnail for export (uses or generates a base64 encoding) Args: ccnode (<ContentNode>): node to derive thumbnail from (if encoding is provided) ccfilemodel (<File>): file to get thumbnail from if no encoding is available Returns <File> model of encoded, resized thumbnail """ encoding = None try: encoding = ccnode.thumbnail_encoding and load_json_string(ccnode.thumbnail_encoding).get('base64') except ValueError: logging.error("ERROR: node thumbnail is not in correct format ({}: {})".format(ccnode.id, ccnode.thumbnail_encoding)) return # Save the encoding if it doesn't already have an encoding if not encoding: try: encoding = get_thumbnail_encoding(str(ccfilemodel)) except IOError: # ImageMagick may raise an IOError if the file is not a thumbnail. Catch that then just return early. logging.error("ERROR: cannot identify the thumbnail ({}: {})".format(ccnode.id, ccnode.thumbnail_encoding)) return ccnode.thumbnail_encoding = json.dumps({ "base64": encoding, "points": [], "zoom": 0, }) ccnode.save() return create_thumbnail_from_base64( encoding, uploaded_by=ccfilemodel.uploaded_by, file_format_id=ccfilemodel.file_format_id, preset_id=ccfilemodel.preset_id )
def test_get_thumbnail_encoding(self): encoding = get_thumbnail_encoding(str(self.thumbnail_fobj)) self.assertEqual(encoding, generated_base64encoding())
def test_get_thumbnail_encoding(self): encoding = get_thumbnail_encoding(str(self.thumbnail_fobj)) self.assertEqual(encoding, generated_base64encoding())