0

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 3

1

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();
}
Sign up to request clarification or add additional context in comments.

3 Comments

How do I put the IFormFile image in my sqlite db? - the method works :')
Is storing images in SQLite a requirement? Using local files is easier in my opinion and does not cause high memory usage when users upload huge images. If you need SQLite please edit your question to give more context about what you already tried.
I'd prefer to save them in my db to store everything in there. I'll edit the question. I'm sorry
0

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.

Comments

0

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");

}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.