ASP.NET Core에서 이미지를 처리하려면 제3사 도구인 SixLabors가 필요하다.

(RC버전이 나올 무렵에 받아서 v1.0.0-rc0001 버전을 쓰고 있었다.)

최근에 본의 아니게 이 SixLabors 이미지 관련 툴을 최신 버전으로 업데이트하게 되었는데...

알고 보니 툴 버그가 아니었고... 굳이 업데이트할 필요까지는 없었다.

뭐, 최신 안정화 버전으로 업데이트했으니, 헛수고를 한 것은 아니지만.

 

 

>> 참조: www.nuget.org/packages/SixLabors.ImageSharp.Web/1.0.1

 

SixLabors.ImageSharp.Web 1.0.1

ImageSharp Middleware for serving images via a url based API.

www.nuget.org

 

문제는... JPG 이미지를 업로드하는데, 아래와 같은 오류가 발생하는 것이었다.

 

Image cannot be loaded. Available decoders:

GIF : GifDecoder
PNG : PngDecoder
JPEG : JpegDecoder
BMP : BmpDecoder

분명히 JPEG 포맷이 맞는데, 지원되지 않는다니...

 

아래 코드에서 대체 무슨 문제가 있었을까?

 

private static bool isValidImage(string filePath)
{
	if (!File.Exists(filePath))
	{
		Debug.WriteLine("isValidImage(): !File.Exists");
		return false;
	}

	using (FileStream imageStream = new FileStream(filePath, FileMode.Open, FileAccess.Read))
	{
		if (imageStream.Length <= 0)
		{
			Debug.WriteLine("isValidImage(): imageStream.Length <= 0");
			return false;
		}

		byte[] bmp    = Encoding.ASCII.GetBytes("BM");     // BMP
		byte[] gif    = Encoding.ASCII.GetBytes("GIF");    // GIF
		byte[] png    = new byte[] { 137, 80, 78, 71 };    // PNG
		byte[] tiff   = new byte[] { 73, 73, 42 };         // TIFF
		byte[] tiff2  = new byte[] { 77, 77, 42 };         // TIFF
		byte[] jpeg   = new byte[] { 255, 216, 255, 224 }; // jpeg
		byte[] jpeg2  = new byte[] { 255, 216, 255, 225 }; // jpeg canon

		byte[] header = new byte[4]; // Change size if needed.
		imageStream.Read(header, 0, header.Length);

		bool isImageHeader =
				bmp.SequenceEqual(header.Take(bmp.Length)) ||
				gif.SequenceEqual(header.Take(gif.Length)) ||
				png.SequenceEqual(header.Take(png.Length)) ||
				tiff.SequenceEqual(header.Take(tiff.Length)) ||
				tiff2.SequenceEqual(header.Take(tiff2.Length)) ||
				jpeg.SequenceEqual(header.Take(jpeg.Length)) ||
				jpeg2.SequenceEqual(header.Take(jpeg2.Length));

		if (isImageHeader)
		{
			try
			{
				Image.Load(imageStream).Dispose();
				imageStream.Close();
				return true;
			}
			catch (Exception ex)
			{
				Debug.WriteLine("isValidImage(): " + ex.Message);
			}
		}
		else
		{
			Debug.WriteLine("isValidImage(): ImageHeader is not any of JPEG, BMP, GIF, PNG");
		}
	}

	return false;
}

 

오류가 발생한 부분은 위 코드의 41번째 줄 Image.Load(imageStream)에서였다.

분명히 JPEG 헤더까지 이상없이 잘 나왔는데, 실제 이미지를 로드하다가 오류가 발생한 것.

그래서 SixLabors 도구의 버전이 낮아서 그런 것인가 의심까지 했었는데... 아니었다.

 

 

.

.

.

.

.

.

.

.

 

 

 

문제는 바로 위에 있었다.

26번째 줄 imageStream.Read(header, 0, header.Length); 이 부분.

이미지 포맷을 비교하기 위해 Stream의 첫 부분부터 4바이트를 읽었는데... 4번째로 위치가 바뀌어 있었던 것!

 

이미지를 정상 로드하려면 Stream의 현재 위치를 맨 처음으로 다시 돌려야 했던 것이다!

 

imageStream.Position = 0;

Image.Load(imageStream).Dispose();

...

 

이 코드가 빠져서 발생한 오류였던 것이다. ㄷㄷ

똑같은 실수를 벌써 몇 번째 반복하는 것인지 원.

이번에는 블로그에 글까지 파서 올려 두었으니 다시 실수를 하지는 않겠지? ㅎ

 

아래 올바른 소스로 다시 써 둔다.

 

private static bool isValidImage(string filePath)
{
	if (!File.Exists(filePath))
	{
		Debug.WriteLine("isValidImage(): !File.Exists");
		return false;
	}

	using (FileStream imageStream = new FileStream(filePath, FileMode.Open, FileAccess.Read))
	{
		if (imageStream.Length <= 0)
		{
			Debug.WriteLine("isValidImage(): imageStream.Length <= 0");
			return false;
		}

		byte[] bmp    = Encoding.ASCII.GetBytes("BM");     // BMP
		byte[] gif    = Encoding.ASCII.GetBytes("GIF");    // GIF
		byte[] png    = new byte[] { 137, 80, 78, 71 };    // PNG
		byte[] tiff   = new byte[] { 73, 73, 42 };         // TIFF
		byte[] tiff2  = new byte[] { 77, 77, 42 };         // TIFF
		byte[] jpeg   = new byte[] { 255, 216, 255, 224 }; // jpeg
		byte[] jpeg2  = new byte[] { 255, 216, 255, 225 }; // jpeg canon

		byte[] header = new byte[4]; // Change size if needed.
		imageStream.Read(header, 0, header.Length);

		bool isImageHeader =
				bmp.SequenceEqual(header.Take(bmp.Length)) ||
				gif.SequenceEqual(header.Take(gif.Length)) ||
				png.SequenceEqual(header.Take(png.Length)) ||
				tiff.SequenceEqual(header.Take(tiff.Length)) ||
				tiff2.SequenceEqual(header.Take(tiff2.Length)) ||
				jpeg.SequenceEqual(header.Take(jpeg.Length)) ||
				jpeg2.SequenceEqual(header.Take(jpeg2.Length));

		if (isImageHeader)
		{
			try
			{
				imageStream.Position = 0;
				Image.Load(imageStream).Dispose();
				imageStream.Close();
				return true;
			}
			catch (Exception ex)
			{
				Debug.WriteLine("isValidImage(): " + ex.Message);
			}
		}
		else
		{
			Debug.WriteLine("isValidImage(): ImageHeader is not any of JPEG, BMP, GIF, PNG");
		}
	}

	return false;
}

 

 



Posted by 떼르미
,


자바스크립트를 허용해주세요!
Please Enable JavaScript![ Enable JavaScript ]