skip to Main Content

I’m creating a Web App in c# and I need to upload an image from an html form into my database.
I tried to do it this way but the binaryformatter can’t be used in api controllers because of security issues.

[HttpGet("imageUploadEndpoint")]
    public IActionResult bytesImage([FromForm] object image)
    {
        BinaryFormatter bf = new BinaryFormatter();
        MemoryStream ms = new MemoryStream();
        bf.Serialize(ms, image);
        //ms.ToArray() should then be uploaded to my sqlite database via entityframework in byte[] format 
        return Ok(ms.ToArray()); //this return was just to see what happened
    }

—IMAGE UPLOAD TO API RESOLVED—

Now I need to put images inside an sqlite db with entityframework. How could I do it?

3

Answers


  1. Chosen as BEST ANSWER

    I solved the upload this way:

    [HttpPost("endpoint")]
        public async Task<IActionResult> Upload(IFormFileCollection image)
        {
            using (MemoryStream fileStream = new MemoryStream()) //img object creation
            {
                await image[0].CopyToAsync(fileStream);
                var img = new { fileStream = fileStream.ToArray(), contentType = image[0].ContentType };
                return File(img.fileStream(), img.contentType)
            }
        }
    

    and i'll put the img object in the sqlite db as a BLOB data value.


  2. Uploading an image to a GET endpoint is not a good idea because they have no request body and are not supposed to change the server state (MDN).

    Instead, I would recommend you to use a POST endpoint and data binding to IFormFileCollection. I am using this inside of a standard MVC controller but don’t know whether it works in an ApiController, too.

    [HttpPost("imageUploadEndpoint")]
    public async Task<IActionResult> Upload(IFormFileCollection files)
    {
        foreach (IFormFile file in files)
        {
            MemoryStream ms = new MemoryStream();
            await file.CopyToAsync(ms);
        }
    
        return Ok();
    }
    

    In one of my open source projects you can find the full implementation of an image upload with ASP.NET Core MVC (GitHub).

    Update for storing in database

    Although I would recommend to store photos as files, you could create an EF Core database context and an entity like this:

    public class FileDbContext : DbContext
    {
        protected override void OnModelCreating(ModelBuilder modelBuilder)
        {
            base.OnModelCreating(modelBuilder);
    
            modelBuilder.Entity<File>().HasKey(f => f.Id);
        }
    }
    
    public class File
    {
        public int Id { get; set; }
        public byte[] Data { get; set; }
    }
    

    Now you can extend your controller:

    private readonly FileDbContext db; // Use constructor injection
    
    [HttpPost("imageUploadEndpoint")]
    public async Task<IActionResult> Upload(IFormFileCollection files)
    {
        foreach (IFormFile file in files)
        {
            using MemoryStream ms = new MemoryStream();
            await file.CopyToAsync(ms);
            File dbFile = new File { Data = ms.ToArray() };
            db.Set<File>().Add(dbFile);
        }
        await db.SaveChangesAsync();
    
        return Ok();
    }
    
    Login or Signup to reply.
  3. My Solution is like –
    I tried using minimal API (.net 7)
    Below is the Model

    public class Photo
    

    {
    public IFormFile? File { get; set; }
    public static async ValueTask<Photo?> BindAsync(HttpContext context, ParameterInfo parameter)
    {
    var form = await context.Request.ReadFormAsync();
    var file = form.Files["file"];
    return new Photo
    {
    File = file
    };
    }
    }

    Also, my user profile data model is like this:

    public class UserProfile {
    public int UserProfileId { get; set; }
    
    public string Name { get; set; }
    public string LastName { get; set; }
    public string MiddleName { get; set; }
    
    public DateTime? DOB { get; set; }
    public string Address { get; set; }
    public string State { get; set; }
    public string Country { get; set; }
    public int? Zipcode { get; set; }
    
    public string AlterEmail { get; set; }
    public string Moblie { get; set; }
    public string Phone { get; set; }
    
    public byte[] Avatar { get; set; } = new byte[0];
    public DateTime? CreatedOn { get; set; }
    public DateTime? UpdatedOn { get; set; }
    
    public virtual LoginEntity? Login { get; set; }
    

    }

    Then used minimal API endpoints:

            loginGroup.MapPost("/upload", async (Photo photo, IndOMDBContext db) =>
        {
            var reader = new StreamReader(photo?.File.OpenReadStream());
            var text = await reader.ReadToEndAsync();
            var avatarCoded = Encoding.ASCII.GetBytes(text);
            var userProfile = await db.UserProfile.Where(p => p.UserProfileId == 2).FirstOrDefaultAsync();
            userProfile.Avatar = avatarCoded;
            await db.SaveChangesAsync();
    
            return Results.Ok(photo?.File.Length);
        }).Accepts<Photo>("multipart/form-data");
    
    }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search