sDima
sDima

Reputation: 396

ASP.NET Core 5.0 serve static files with modified response

When requesting images from Uploads folder with a height or width parameter, they must automatically shrink to the desired size. However, no matter what I do, I cannot stop writing in response the original image. How do I modify the response of static files handler?

In my Startup.cs I have:

string uploadsDirPath = Path.GetFullPath("Uploads".TrimStart('~', '/'), env.ContentRootPath);
Directory.CreateDirectory(uploadsDirPath);

app.UseStaticFiles(new StaticFileOptions
{
    FileProvider = new PhysicalFileProvider(uploadsDirPath),
    RequestPath = new PathString("/Uploads"),
    ContentTypeProvider = fileExtensionProvider,
    OnPrepareResponse = async (context) =>
    {
        context.Context.Response.Headers[HeaderNames.CacheControl] = "public,must-revalidate,max-age=" + TimeSpan.FromDays(365).TotalSeconds;

        // Modify only images.
        if (context.Context.Response.ContentType.StartsWith("image/"))
        {
            int.TryParse(context.Context.Request.Query["width"], out int width);
            int.TryParse(context.Context.Request.Query["height"], out int height);

            if ((width == 0 && height == 0) || context.Context.Response.ContentType == "image/svg+xml" || context.Context.Response.ContentType == "image/gif")
                return;

            // SkiaSharp resize.
            using (var original = SKBitmap.Decode(context.File.PhysicalPath))
            {
                if ((width == 0 || width > original.Width) && (height == 0 || height > original.Height))
                    return;

                // Respect original ratio.
                if (width > 0)
                    height = original.Height * width / original.Width;
                else
                    width = original.Width * height / original.Height;

                using (var resized = original.Resize(new SKImageInfo(width, height), SKFilterQuality.High))
                {
                    if (context.Context.Request.Headers[HeaderNames.Accept].ToString().Contains("image/webp"))
                    {
                        var stream = resized.Encode(SKEncodedImageFormat.Webp, 80).AsStream();
                        context.Context.Response.ContentType = "image/webp";
                        context.Context.Response.Body = stream;
                        context.Context.Response.ContentLength = stream.Length;
                        // not working.
                        await context.Context.Response.CompleteAsync();
                        return;
                    }
                }
            }
        }
    }
});

Upvotes: 2

Views: 1384

Answers (1)

ycrumeyrolle
ycrumeyrolle

Reputation: 525

You are trying to use the static files middleware for serving dynamic files. You can't modify static content as it is static.

Write your own middleware that combine a PhysicalFileProvider and the shrinking code that you have.

There are some blogs on this, like https://www.paddo.org/asp-net-core-image-resizing-middleware/

Upvotes: 2

Related Questions