You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

9.3 KiB

sidebar_position title
2 Image display

Use Base64 images

The image files is not the best way to save image, in many architecture the image are saving in the database.

We modify the code to save the image in the database ;)

Update the model

Open the item model and add a property which will contain the base64 image.

public class Item
{
	public int Id { get; set; }
	public string DisplayName { get; set; }
	public string Name { get; set; }
	public int StackSize { get; set; }
	public int MaxDurability { get; set; }
	public List<string> EnchantCategories { get; set; }
	public List<string> RepairWith { get; set; }
	public DateTime CreatedDate { get; set; }
	public DateTime? UpdatedDate { get; set; }
	// highlight-next-line
	public string ImageBase64 { get; set; }
}
public class ItemModel
{
	...

	// highlight-next-line
	public string ImageBase64 { get; set; }
}

Update the local service

We will also modify the local service to save the image in base64, we remove all reference to save image.

Remove the highlight code !

public async Task Add(ItemModel model)
{
	// Get the current data
	var currentData = await _localStorage.GetItemAsync<List<Item>>("data");

	// Simulate the Id
	model.Id = currentData.Max(s => s.Id) + 1;

	// Add the item to the current data
	currentData.Add(ItemFactory.Create(model));

// highlight-start
	// Save the image
	var imagePathInfo = new DirectoryInfo($"{_webHostEnvironment.WebRootPath}/images");

	// Check if the folder "images" exist
	if (!imagePathInfo.Exists)
	{
		imagePathInfo.Create();
	}

	// Determine the image name
	var fileName = new FileInfo($"{imagePathInfo}/{model.Name}.png");

	// Write the file content
	await File.WriteAllBytesAsync(fileName.FullName, model.ImageContent);
// highlight-end

	// Save the data
	await _localStorage.SetItemAsync("data", currentData);
}

public async Task Update(int id, ItemModel model)
{
	// Get the current data
	var currentData = await _localStorage.GetItemAsync<List<Item>>("data");

	// Get the item int the list
	var item = currentData.FirstOrDefault(w => w.Id == id);

	// Check if item exist
	if (item == null)
	{
		throw new Exception($"Unable to found the item with ID: {id}");
	}

// highlight-start
	// Save the image
	var imagePathInfo = new DirectoryInfo($"{_webHostEnvironment.WebRootPath}/images");

	// Check if the folder "images" exist
	if (!imagePathInfo.Exists)
	{
		imagePathInfo.Create();
	}

	// Delete the previous image
	if (item.Name != model.Name)
	{
		var oldFileName = new FileInfo($"{imagePathInfo}/{item.Name}.png");

		if (oldFileName.Exists)
		{
			File.Delete(oldFileName.FullName);
		}
	}

	// Determine the image name
	var fileName = new FileInfo($"{imagePathInfo}/{model.Name}.png");

	// Write the file content
	await File.WriteAllBytesAsync(fileName.FullName, model.ImageContent);
// highlight-end

	// Modify the content of the item
	ItemFactory.Update(item, model);

	// Save the data
	await _localStorage.SetItemAsync("data", currentData);
}

public async Task Delete(int id)
{
	// Get the current data
	var currentData = await _localStorage.GetItemAsync<List<Item>>("data");

	// Get the item int the list
	var item = currentData.FirstOrDefault(w => w.Id == id);

	// Delete item in
	currentData.Remove(item);

// highlight-start
	// Delete the image
	var imagePathInfo = new DirectoryInfo($"{_webHostEnvironment.WebRootPath}/images");
	var fileName = new FileInfo($"{imagePathInfo}/{item.Name}.png");

	if (fileName.Exists)
	{
		File.Delete(fileName.FullName);
	}
// highlight-end

	// Save the data
	await _localStorage.SetItemAsync("data", currentData);
}

Update the factory

This is in the factory that we transform the image to base64.

Change the code of the factory :

public static ItemModel ToModel(Item item, byte[] imageContent)
{
	return new ItemModel
	{
		Id = item.Id,
		DisplayName = item.DisplayName,
		Name = item.Name,
		RepairWith = item.RepairWith,
		EnchantCategories = item.EnchantCategories,
		MaxDurability = item.MaxDurability,
		StackSize = item.StackSize,
		ImageContent = imageContent,
// highlight-next-line
		ImageBase64 = string.IsNullOrWhiteSpace(item.ImageBase64) ? Convert.ToBase64String(imageContent) : item.ImageBase64
	};
}

public static Item Create(ItemModel model)
{
	return new Item
	{
		Id = model.Id,
		DisplayName = model.DisplayName,
		Name = model.Name,
		RepairWith = model.RepairWith,
		EnchantCategories = model.EnchantCategories,
		MaxDurability = model.MaxDurability,
		StackSize = model.StackSize,
		CreatedDate = DateTime.Now,
// highlight-next-line
		ImageBase64 = Convert.ToBase64String(model.ImageContent)
	};
}

public static void Update(Item item, ItemModel model)
{
	item.DisplayName = model.DisplayName;
	item.Name = model.Name;
	item.RepairWith = model.RepairWith;
	item.EnchantCategories = model.EnchantCategories;
	item.MaxDurability = model.MaxDurability;
	item.StackSize = model.StackSize;
	item.UpdatedDate = DateTime.Now;
// highlight-next-line
	item.ImageBase64 = Convert.ToBase64String(model.ImageContent);
}

Update the views

Remove the highlight code !

...

protected override async Task OnInitializedAsync()
{
	var item = await DataService.GetById(Id);

	var fileContent = await File.ReadAllBytesAsync($"{WebHostEnvironment.WebRootPath}/images/default.png");

// highlight-start
	if (File.Exists($"{WebHostEnvironment.WebRootPath}/images/{itemModel.Name}.png"))
	{
		fileContent = await File.ReadAllBytesAsync($"{WebHostEnvironment.WebRootPath}/images/{item.Name}.png");
	}
// highlight-end

	// Set the model with the item
	itemModel = ItemFactory.ToModel(item, fileContent);
}
...
...

<p>
	<label>
		Current Item image:
		<img src="data:image/png;base64, @(itemModel.ImageBase64)" class="img-thumbnail" title="@itemModel.DisplayName" alt="@itemModel.DisplayName" style="min-width: 50px; max-width: 150px"/>
	</label>
</p>

...
...

<DataGridColumn TItem="Item" Field="@nameof(Item.Id)" Caption="Image">
	<DisplayTemplate>
		@if (!string.IsNullOrWhiteSpace(context.ImageBase64))
		{
			<img src="data:image/png;base64, @(context.ImageBase64)" class="img-thumbnail" title="@context.DisplayName" alt="@context.DisplayName" style="min-width: 50px; max-width: 150px" />
		}
		else
		{
			<img src="images/default.png" class="img-thumbnail" title="@context.DisplayName" alt="@context.DisplayName" style="max-width: 150px"/>
		}
	</DisplayTemplate>
</DataGridColumn>

...

Concept: Base64 Images

To understand base64 images, first lets understand why we need it. Web developers from all around the world is currently trying to minimise unusual data to maximise their website performance. Website performance can be optimised by reducing page size, reducing number of requests, position of scripts and stylesheets & many other factors affect webpage speed. Base64 method is used to minimise the server requests by integrating image data in HTML code.

Base64 method uses Data URI and its syntax is as below:

data:[<MIMETYPE>][;charset=<CHARSET>][;base64],<DATA>

To integrate it in HTML you have to write html img tag code like this:

<img alt="coderiddles" src="data:image/jpg;base64,S)OWE902WEIWUOLKASJODIIWJ9878978JKKJKIWEURU4954590EJ09JT9T99TIR32EQ2EKJDKSDFDNXZCNBAC3SASDASD45ASD5ASD5A4SDASD54DS56DB67V6VBN78M90687LKJKSDFJSDF76F7S7D78F9SDF78S6FSDF9SDFSFSDGFSDFSDLFJSDF7SD86FSDFSDFSDFS8F89SDIFOSDFSFJHKJL" />

We can easily convert base64 images using online tool.

We can also integrate base64 images inside stylesheet (background-image property).

.imagediv 
{
    background: url(data:image/jpg;base64,S)OWE902WEIWUOLKASJODIIWJ9878978JKKJKIWEURU4954590EJ09JT9T99TIR32EQ2EKJDKSDFDNXZCNBAC3SASDASD45ASD5ASD5A4SDASD54DS56DB67V6VBN78M90687LKJKSDFJSDF76F7S7D78F9SDF78S6FSDF9SDFSFSDGFSDFSDLFJSDF7SD86FSDFSDFSDFS8F89SDIFOSDFSFJHKJL);
}

Base64 images can increase performance?

If we encode all our websites small images, wrap them inside css or html code. Doing this will reduce the number of HTTP requests because client (browser) dont have to issue separate request for images. That will definitely increase performance of website. Because most of page load time is taken for transferring data over internet. Not to process it on server.

Advantages of Base64 images:

  • Removes separate HTTP Requests for image loading by wrapping encoded image code inside css or HTML.
  • Image encoded data can be saved inside database and can generate image file. Just incase we lost image file copy.

Disadvantages Base64 images:

  • Though Base64 increases performance but be careful. Doing so will increase image size approximately 20-25%. than what it is actually in its binary form. So more data has to be transferred on internet. For mobile devices it is a bit drawback.
  • Even if we apply gzip compression, doing so will only decrease css file size to around 10-12%.
  • IE6 & IE7 not supports Data URI which means base64 images will not be loaded in ie6 & ie7 browsers.
  • If you apply base64 encoding to lots of medium sized images it will increase HTML content size or CSS content size. So browser has to do roundtrip to get full content.