You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

ASP.NET Core MVC实现图片上传至SQLite的技术求助

嘿,我来帮你搞定这个图片上传到SQLite的问题!作为ASP.NET Core MVC新手,把图片转成字节流存在数据库里是个很直接的方案,我一步步给你讲怎么修改现有代码:

1. 修改Model(适配字节流存储)

原来的Poster是string类型,我们需要改成byte[]来存储图片的字节数据,同时添加一个不映射到数据库的IFormFile属性用来接收上传的文件(这个属性只是临时用来处理上传,不用存在数据库里):

using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using Microsoft.AspNetCore.Http;

public class Movie 
{ 
    public int ID { get; set; } 

    [StringLength(60, MinimumLength = 3)] 
    [Required] 
    public string Title { get; set; } 

    [Display(Name = "Release Date")] 
    [DataType(DataType.Date)] 
    public DateTime ReleaseDate { get; set; } 

    [RegularExpression(@"^[A-Z]+[a-zA-Z""'\s-]*$")] 
    [Required] 
    [StringLength(30)] 
    public string Genre { get; set; } 

    [Range(1, 100)] 
    [DataType(DataType.Currency)] 
    public decimal Price { get; set; } 

    [RegularExpression(@"^[A-Z]+[a-zA-Z""'\s-]*$")] 
    [StringLength(5)] 
    [Required] 
    public string Rating { get; set; } 

    // 存储图片字节流的核心属性,对应SQLite的BLOB类型
    public byte[]? Poster { get; set; } 

    // 临时接收上传文件的属性,[NotMapped]标记它不生成数据库列
    [NotMapped]
    [DataType(DataType.Upload)] 
    [Display(Name = "Upload Movie Poster")] 
    [Required(ErrorMessage = "Please choose an image file to upload.")]
    public IFormFile? PosterFile { get; set; } 
}

修改完Model后,别忘了更新数据库结构,在终端运行以下命令:

dotnet ef migrations add AddPosterByteArray
dotnet ef database update
2. 修改Controller(处理文件转字节流)

以你提供的Edit方法为例,我们需要调整参数绑定,处理上传的文件并将其转换为字节数组,赋值给Movie.Poster属性。顺带也给你补充Create方法的参考逻辑:

Edit方法修改:

public async Task<IActionResult> Edit(int id, [Bind("ID,Title,ReleaseDate,Genre,Price,Rating")] Movie movie, IFormFile? posterFile) 
{ 
    if (id != movie.ID) 
    { 
        return NotFound(); 
    }

    // 处理上传的文件
    if (posterFile != null && posterFile.Length > 0)
    {
        // 验证文件类型(只允许常见图片格式)
        var allowedExtensions = new[] { ".jpg", ".jpeg", ".png", ".gif" };
        var fileExtension = Path.GetExtension(posterFile.FileName).ToLower();
        if (!allowedExtensions.Contains(fileExtension))
        {
            ModelState.AddModelError("PosterFile", "Only JPG, JPEG, PNG, GIF files are allowed.");
            return View(movie);
        }

        // 将文件流转换为字节数组
        using (var memoryStream = new MemoryStream())
        {
            await posterFile.CopyToAsync(memoryStream);
            movie.Poster = memoryStream.ToArray();
        }
    }

    if (ModelState.IsValid) 
    { 
        try 
        { 
            _context.Update(movie); 
            await _context.SaveChangesAsync(); 
        } 
        catch (DbUpdateConcurrencyException) 
        { 
            if (!MovieExists(movie.ID)) 
            { 
                return NotFound(); 
            } 
            else 
            { 
                throw; 
            } 
        } 
        return RedirectToAction(nameof(Index)); 
    } 
    return View(movie); 
}

Create方法参考:

public async Task<IActionResult> Create([Bind("Title,ReleaseDate,Genre,Price,Rating")] Movie movie, IFormFile? posterFile)
{
    if (posterFile != null && posterFile.Length > 0)
    {
        // 重复文件验证和转字节流逻辑
        var allowedExtensions = new[] { ".jpg", ".jpeg", ".png", ".gif" };
        var fileExtension = Path.GetExtension(posterFile.FileName).ToLower();
        if (!allowedExtensions.Contains(fileExtension))
        {
            ModelState.AddModelError("PosterFile", "Only JPG, JPEG, PNG, GIF files are allowed.");
            return View(movie);
        }

        using (var memoryStream = new MemoryStream())
        {
            await posterFile.CopyToAsync(memoryStream);
            movie.Poster = memoryStream.ToArray();
        }
    }

    if (ModelState.IsValid)
    {
        _context.Add(movie);
        await _context.SaveChangesAsync();
        return RedirectToAction(nameof(Index));
    }
    return View(movie);
}
3. 修改View(对应新的上传属性)

把原来绑定Poster的输入框改成绑定PosterFile,同时可以添加图片预览功能(如果已有海报的话):

<form asp-action="Edit" enctype="multipart/form-data">
    <div asp-validation-summary="ModelOnly" class="text-danger"></div>
    <input type="hidden" asp-for="ID" />
    
    <!-- 其他原有表单字段保持不变 -->
    
    <div class="form-group">
        <label asp-for="PosterFile" class="control-label"></label>
        <input type="file" asp-for="PosterFile" class="form-control" accept="image/*" />
        <span asp-validation-for="PosterFile" class="text-danger"></span>
        
        <!-- 预览已存在的海报 -->
        @if (Model.Poster != null)
        {
            <div class="mt-2">
                <img src="data:image/jpeg;base64,@Convert.ToBase64String(Model.Poster)" 
                     alt="Movie Poster" style="max-width: 200px; max-height: 300px;" />
            </div>
        }
    </div>
    
    <div class="form-group">
        <input type="submit" value="Save" class="btn btn-default" />
    </div>
</form>

这里加了accept="image/*"来限制用户只能选择图片文件,同时用Base64格式把数据库里的字节数组转换成可直接显示的图片。

4. 列表页显示海报(可选)

如果想在Index视图里展示电影海报缩略图,可以这样写:

@foreach (var item in Model)
{
    <tr>
        <td>
            @if (item.Poster != null)
            {
                <img src="data:image/jpeg;base64,@Convert.ToBase64String(item.Poster)" 
                     alt="Poster" style="width: 50px; height: 75px; object-fit: cover;" />
            }
            else
            {
                <span>No Poster</span>
            }
        </td>
        <td>@Html.DisplayFor(modelItem => item.Title)</td>
        <!-- 其他列内容 -->
    </tr>
}

这样一套操作下来,你就能实现把图片转成字节流存储到SQLite,并且在视图里正常显示啦!

内容的提问来源于stack exchange,提问作者Krunal Bodiwala

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.28 04:23:48