Search code examples
sql-serverasp.net-corefilestreamfile-storage

How to make FileStream files available to a web app


I've been trying to figure out the best way of making files stored in a Sql Server db as a FILESTREAM available to a web application.

Basically, I have a Web App written with Vue, an ASP.NET CORE WebApi backing it and when the user uploads an image (which is stored in the DB as a varbinary(max) FILESTREAM) the user should be able to view the image in browser.

I want to use an <img src="{url to image}"/>

So the question is: How do I get the {url to image} for the img tag from the record in the db. And I need it to 1. Work across multiple servers, so if the web app and db are on different servers. and 2. i need to url to be an alias so as not to give away the folder structure where the files are stored.

I'm also open to any suggestions on how to handle file storage differently if necessary.

Thanks.


Solution

  • If it's a small image (under 5KiB) you could get-away with Base64-encoding the raw data into an inline data: URI for the image.

    Otherwise, you'll need to write a new Controller Action that only serves up image data. Remember to set the correct content-type too. Pass in the record key as a URI parameter.

    [Route("/record-images/{recordPrimaryKey}")]
    public async Task<IActionResult> GetImage( Int32 recordPrimaryKey )
    {
        using( SqlConnection c = ... )
        using( SqlCommand cmd = c.CreateCommand() )
        {
            cmd.CommandText = "SELECT ..."; // I assume the raw file data is returned through `SqlDataReader`. I assume that FILESTREAM is just a back-end storage concern.
            using( SqlDataReader rdr = await cmd.ExecuteReaderAsync() )
            {
                if( !rdr.Read() ) return this.NotFound();
    
                Byte[] imageData = rdr.GetBytes( 0 );
                String contentType = rdr.GetString( 1 );
                return this.File( imageData, contentType );
            }
        }
    }