question

RafaelMassula-3862 avatar image
0 Votes"
RafaelMassula-3862 asked ispilante-5660 commented

Best practice for saving image in database

Hi guys!
I have a lot of doubts about like saving images in database. I have a project in Asp Net Core, with somes models and i would like saving product with a list images. I thought using base64, but not know if good idea. Some sugestion? Remembiring that is a complex model i need to receive:
{
"Description": "Strogonoff de frango sem glúten/ lactose",
"Price": 17.90,
"Size": 300,
"ManufactoringDate": "2021-12-26",
"Files":[
{
"Bytes": "base64",
"Description": "prato-principal",
"FileExtension": ".png",
"Size": 26498
}
]
}

sql-server-generaldotnet-aspnet-core-mvcdotnet-aspnet-core-webapi
5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

ZhiLv-MSFT avatar image
0 Votes"
ZhiLv-MSFT answered ispilante-5660 commented

Hi @RafaelMassula-3862,

Base on your previous question, you can configure one-to-many relationship between the Product and Photo table, then we can add/update/delete the related entities via the navigation property. More detail information see Relationships.

So, I suggest you could add the navigation property in the Product model. Code like this:

 public class Product
 { 
     [Key]
     public int Id { get; set; } 
     [Required]
     public string Description { get; set; } 
     [Required]
     public decimal Price { get; set; } 
     [Required]
     public int Size { get; set; } 
     [Required]
     public DateTime ManufactoringDate { get; set; } 
     [Required]
     public DateTime ExpirationDate { get; set; }

     //navigation property: configure one-t0-many relationship with Photo 
     public List<Photo> Photos { get; set; }

     [FromForm]
     [NotMapped]
     public IFormFileCollection Files { get; set; } 
 }
 public class Photo
 {
     [Key]
     public int Id { get; set; }
     public byte[] Bytes { get; set; }
     public string Description { get; set; }
     public string FileExtension { get; set; }
     public decimal Size { get; set; }
     public int ProductId { get; set; }
     [ForeignKey("ProductId")]
     public Product Product { get; set; }
 }

Then, in the action method: you can refer to the following sample to create product.

     [HttpGet]
     public IActionResult CreateProduct()
     {
         return View();
     }
     [HttpPost]
     public async Task<IActionResult> CreateProductAsync([FromForm]Product product)
     {
         if (!ModelState.IsValid)
             return (IActionResult)Task.FromResult(product);
         //create a new Product instance.
         Product newproduct = new()
         {
             Description = product.Description,
             Price = product.Price,
             Size = product.Size,
             ManufactoringDate = product.ManufactoringDate
         };

         //create a Photo list to store the upload files.
         List<Photo> photolist = new List<Photo>();
         if (product.Files.Count > 0)
         {
             foreach(var formFile in product.Files)
             {
                 if (formFile.Length > 0)
                 {  
                     using (var memoryStream = new MemoryStream())
                     {
                         await formFile.CopyToAsync(memoryStream);
                         // Upload the file if less than 2 MB
                         if (memoryStream.Length < 2097152)
                         {
                             //based on the upload file to create Photo instance.
                             //You can also check the database, whether the image exists in the database.
                             var newphoto = new Photo()
                             {
                                 Bytes = memoryStream.ToArray(),
                                 Description = formFile.FileName,
                                 FileExtension = Path.GetExtension(formFile.FileName),
                                 Size = formFile.Length,                                    
                             };
                             //add the photo instance to the list.
                             photolist.Add(newphoto);
                         }
                         else
                         {
                             ModelState.AddModelError("File", "The file is too large.");
                         }
                     }
                 }
             }
         }
         //assign the photos to the Product, using the navigation property.
         newproduct.Photos = photolist;

         _context.Products.Add(newproduct);
         _context.SaveChanges();
           

         return View();
     }

The result is like this: we can see that, even though we just add the product the to the Product table, since we have configure relationship via the navigation property, the relates photo will also add to the Photo table.

162114-2.gif

Finally, you can refer the Loading Related Data to load the related entities.


If the answer is the right solution, please click "Accept Answer" and kindly upvote it. If you have extra questions about this answer, please click "Comment".
Note: Please follow the steps in our documentation to enable e-mail notifications if you want to receive the related email notification for this thread.

Best regards,
Dillion

· 2
5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

I have tried this solution and added the input for the form as the following:
<div class="form-group">
<label asp-for="Files" class="control-label"></label>
<input asp-for="Files" class="form-control" multiple />
<span asp-validation-for="Files" class="text-danger"></span>
</div>

However, when I submit the form the files property of product is null. Any idea why this happens and how to fix it?

0 Votes 0 ·

How does a GET method would look like ?

Like if I would like just to send the image stored with a GET method, how would I do that ?

0 Votes 0 ·
MartinCairney-6481 avatar image
0 Votes"
MartinCairney-6481 answered

You can either consider the use of the VARBINARY(MAX) datatype to store images directly in the data base or have a look at FILESTREAM which can let you store the image files outside the database but with access and controls via SQL Server itself.


5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.