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
相关产品推荐
相关产品推荐

