0

I'm new to back end programming with ASP.NET. I'm wondering how to deal images that are either taken with the users camera or just uploaded with their gallery. At the moment I have a nice little 'DeliveryItem' object with things like Strings for name and Ints for quantity and all that, but essentially what I want now is public image ItemImage { get; set; }.

I saw something like

public class Image
{
    public int Id { get; set; }
    public string ImageTitle { get; set; }
    public byte[] ImageData { get; set; }
}

But if this is the case then heh, I got a nice day of scratching my head to look forward to :)

How does a back end deal with this kind of media? Or videos, voice notes, gifs for that matter. Do we break them down into something like a resource string and host it online? It's hooked up to a SQL database so clearly it can't be like that, I'm just trying to get an idea here and couldn't find a noob friendly way of explaining it in my google searching.

Thanks for any insight!

flutterisbae
  • 305
  • 3
  • 10
  • Properties should not return arrays – Caius Jard Jan 04 '21 at 23:47
  • 1
    This question can only really be answered with opinions.. it is my opinion that a file should remain as such in a file system because that's usually the least headache way of working with it. Put the path and meta in the db if you want but endeavour to make it so that the file is just bytes on disk so you don't have to code *everything* that does something with it. Want to serve it over http? If it's on disk on a web server - just tell the browser the url to it. If it's in a database, get writing the code to extract it and write it to the response, then develop caching for it, then... – Caius Jard Jan 04 '21 at 23:51
  • Are you asking about receiving the input from the user or storage solutions? – greenjaed Jan 04 '21 at 23:51
  • Have you checked out the documentation? It is an informative, great read. https://learn.microsoft.com/en-us/aspnet/core/mvc/models/file-uploads?view=aspnetcore-3.1 – LinkedListT Jan 05 '21 at 01:14

1 Answers1

4

How does a back end deal with this kind of media? Or videos, voice notes, gifs for that matter. Do we break them down into something like a resource string and host it online? It's hooked up to a SQL database so clearly it can't be like that, I'm just trying to get an idea here and couldn't find a noob friendly way of explaining it in my google searching.

It depends on your scenario. In my opinion, if upload small file, I prefer to upload the image to the database (using byte array), if upload large file, I might upload them in the Physical storage (file system or network share). You can also check the common storage options for files.

When upload file to the database, we can specify a page model property for the class that includes an IFormFile:

public class BufferedSingleFileUploadDbModel : PageModel {
    ...

    [BindProperty]
    public BufferedSingleFileUploadDb FileUpload { get; set; }

    ... }

public class BufferedSingleFileUploadDb {
    [Required]
    [Display(Name="File")]
    public IFormFile FormFile { get; set; } }

The FileUpload is used in the Razor Pages form:

<form enctype="multipart/form-data" method="post">
    <dl>
        <dt>
            <label asp-for="FileUpload.FormFile"></label>
        </dt>
        <dd>
            <input asp-for="FileUpload.FormFile" type="file">
        </dd>
    </dl>
    <input asp-page-handler="Upload" class="btn" type="submit" value="Upload">
</form>

When the form is POSTed to the server, copy the IFormFile to a stream and save it as a byte array in the database.

public async Task<IActionResult> OnPostUploadAsync()
{
    using (var memoryStream = new MemoryStream())
    {
        await FileUpload.FormFile.CopyToAsync(memoryStream);

        // Upload the file if less than 2 MB
        if (memoryStream.Length < 2097152)
        {
            var file = new AppFile()
            {
                Content = memoryStream.ToArray()
            };

            _dbContext.File.Add(file);

            await _dbContext.SaveChangesAsync();
        }
        else
        {
            ModelState.AddModelError("File", "The file is too large.");
        }
    }

    return Page();
}

If we want to upload files to the physical storage, we can use the Path.GetTempFileName to return a full path for a file, including the file name. Then, saves the files to the local file system using a file name generated by the app. After that we could use the file path to display the image or save the file path to the database. Code as below:

public async Task<IActionResult> OnPostUploadAsync(List<IFormFile> files)
{
    long size = files.Sum(f => f.Length);

    foreach (var formFile in files)
    {
        if (formFile.Length > 0)
        {
            var filePath = Path.GetTempFileName();

            using (var stream = System.IO.File.Create(filePath))
            {
                await formFile.CopyToAsync(stream);
            }
        }
    }

    // Process uploaded files
    // Don't rely on or trust the FileName property without validation.

    return Ok(new { count = files.Count, size });
}

More detail sample code, you could check:

Upload small files with buffered model binding to physical storage

Upload small files with buffered model binding to a database

Upload And Display Image In ASP.NET Core 3.1

Besides, about choosing a database or Physical storage, you can also refer the following threads:

Storing images in SQL database vs storing images in seperate folder and using URL image path

In ASP.NET is it better to store an uploaded file into a relational database, or put it into the file system?

Zhi Lv
  • 18,845
  • 1
  • 19
  • 30