Handling images WebAPI (+examples)

Handling images WebAPI (+examples)

WebAPI is used to serve data from server. One time of data could be images. In this post I will show how to write WebAPI methods operating on images data.

So at first we must decide where we want to store our images. Let’s suppose, that we have database that store our application data. We have 2 possibilities: to store images in files or directly in database. This two approaches has following adventages:

  • files
    • easy to test
    • fast
    • requires additional backup strategy
  • database
    • scalable
    • could be joined with db objects (no name conflicts)
    • transactional integrity
    • easy to apply permissions

Based on this points, you can see that storing images in database could be preferable when image is part of entities in your system i.e. photo of product. So we focus on this type of storing. You can easily change.

Handling images

GET

[HttpGet]
[Route("{id}/image")]
public HttpResponseMessage GetImage(int id)
{
	var image = _service.GetImage(id);

	MemoryStream ms = new MemoryStream();
	HttpResponseMessage result = new HttpResponseMessage(HttpStatusCode.OK);
	result.Content = new ByteArrayContent(image);
	result.Content.Headers.ContentType = new MediaTypeHeaderValue("image/png");
	return result;
}

As you can see, there is a MemoryStream, that returns image data to response. Also we must add ContentType header to define type of our image.

DELETE

This method is simple and trival

[HttpDelete]
[Route("{id}/image")]
public void DeleteImage(int id)
{
	_service.Remove(id);
}

POST

This part is a bit tricky at first you need to read multipart stream and then join each of part to one byte array. This array contains final image data that could be saved to database.

[HttpPost]
[Route("{id}/image")]
public async Task<HttpResponseMessage> PostImage(int id)
{
	if (Request.Content.IsMimeMultipartContent())
	{
		string fullPath = HttpContext.Current.Server.MapPath("~/uploads");
		MultipartFormDataStreamProvider streamProvider = new MultipartFormDataStreamProvider(fullPath);
		var task = await Request.Content.ReadAsMultipartAsync(streamProvider).ContinueWith(t =>
		{
			if (t.IsFaulted || t.IsCanceled)
				throw new HttpResponseException(HttpStatusCode.InternalServerError);
			MemoryStream ms = new MemoryStream();
			foreach (var file in streamProvider.FileData)
			{
				var info = new FileInfo(file.LocalFileName);
				var data = File.ReadAllBytes(info.FullName);
				ms.Write(data, 0, data.Length);
			}
			_service.UpdateImage(ms.ToArray());
			return new HttpResponseMessage(HttpStatusCode.OK);
		});
		return task;
	}
	else
	{
		throw new HttpResponseException(Request.CreateResponse(HttpStatusCode.NotAcceptable, "Invalid Request!"));
	}
}