首页 > 解决方案 > 如何使用 .NET Core API 将图像文件上传到数据库?

问题描述

我正在创建一个用户可以发布的应用程序,比如论坛。我正在尝试将图像和文本加载到数据库中,为此,我有两个表,它们都通过 id 相关联。我想出了如何加载文本内容,但我真的不知道如何对图像内容做同样的事情。我正在使用带有相应控制器的 MVC 视图来使用 API。

我正在使用的模型:

public class ForumThemeModel
{
    public ForumThemeModel()
    {
        Themes = new HashSet<Theme>();
    }

    //forum table
    [Key]
    public int IdForum { get; set; }
    public string PostTittle { get; set; }

    //theme table
    public int? Idtheme { get; set; }
    public string TextContent { get; set; }
    public int? IdForum { get; set; }
    public IFormFile ContentFile { get; set; } //where the image will be stored
    public string FileNameA { get; set; }
    public string FileType { get; set; }
}

创建帖子的 API 控制器:

    [HttpPost]
    [Consumes("multipart/form-data")]
    [Route("createPost")]
    public async Task<IActionResult> createPost([FromBody]ForumThemeModel model)
    {
        Forum forum = new Forum();

        Theme theme = new Theme();

        var fileName = Path.GetFileName(model.FileNameA);
        var fileExt = Path.GetExtension(fileName);
        var newFileName = String.Concat(Convert.ToString(Guid.NewGuid()), fileExt);

        using(var target = new MemoryStream())
        {
            await model.ContentFile.CopyToAsync(target);
            theme.ContentFile = target.ToArray();
        }

        forum.PostTittle = model.PostTittle;
        theme.FileNameA = newFileName;
        theme.FileType = fileExt;

        var postTittle = new SqlParameter("@postTittle", forum.PostTittle);
        var textContent = new SqlParameter("@textContent", theme.TextContent);
        var content_file = new SqlParameter("@content_file", theme.ContentFile);
        var file_name_a = new SqlParameter("@file_name_a", theme.FileNameA);
        var FileType = new SqlParameter("@FileType", theme.FileType);

        //saves everything to database

        return Ok();
    }

使用 API 的 MVC 控制器:

    [HttpPost]
    public IActionResult createPost(ForumThemeModel model)
    {
        HttpClient hc = new HttpClient();
        hc.BaseAddress = new Uri("https://localhost:44325/api/Users");

        var userPost = hc.PostAsJsonAsync<ForumThemeModel>("Users/createPost", model);

        userPost.Wait();
        
        //do something when the resquest result is successful
    }

MVC控制器的视图:

@model Huerbog.Models.Request.ForumThemeModel

@{
     ViewData["Title"] = "CreatePost";
 }
 <hr />
 <div class="row">
    <div class="col-12 col-md-9">
        <form enctype="multipart/form-data" asp-action="createPost">
           <div asp-validation-summary="ModelOnly" class="text-danger"></div>

           <div class="form-group h4">
              <label asp-for="PostTittle" class="control-label">Tittle</label>
              <input asp-for="PostTittle" class="form-control" />
              <span asp-validation-for="PostTittle" class="text-danger"></span>
           </div>
           <div class="form-group h4">
              <label asp-for="Content" class="control-label">Content of the post</label>
              <textarea rows="5" asp-for="Content" class="form-control"></textarea>
              <span asp-validation-for="Content" class="text-danger"></span>
           </div>
           <div class="form-group h4">
              <label asp-for="ContentFile" class="control-label">Imagen:</label><br />
              <input class="form-control-file" multiple asp-for="ContentFile" type="file" />
           </div>
           <div class="form-group h4">
              <input type="submit" value="Create post" class="btn btn-primary" />
           </div>
         </form>
    </div>
 </div>

因此,我已阅读有关上传图像或文件的信息,它表明enctype = "multipart / form-data" 在数据库中上传图像或不同类型的文件时,该属性应出现在视图中,由于该属性,会发生两件事:第一件事是当我离开该属性时在视图中,MVC 控制器不使用 API 控制器,但模型从文件或图像中接收信息,例如名称、文件类型等。第二个是当我从视图中删除属性时,在这种情况下MVC 控制器使用 API 控制器,但模型不包含有关文件或图像的任何内容。在这两种情况下,模型都会接收到文本内容,但由于缺少有关图像的信息,它也不会被数据库保存。

我不太确定enctype = "multipart / form-data"属性是否是主要原因,但正如我之前所说,在图像上传之前,文本内容运行良好并且enctype = "multipart / form-data"不存在。

我在 img 上传上停留了一段时间,真的我不知道该怎么做,感谢任何帮助。

标签: c#asp.net-mvcasp.net-corefile-uploadasp.net-core-webapi

解决方案


public IFormFile ContentFile { get; set; }

首先请注意,该PostAsJsonAsync方法会将模型数据序列化为 JSON 然后发送到请求正文中,序列化 a 没有意义FormFile,会导致错误。

要实现从 MVC 控制器操作中使用 API 来上传文件和其他数据的需求,您可以参考以下示例代码。

[HttpPost]
public async Task<IActionResult> CreatePost(ForumThemeModel model)
{
    var formContent = new MultipartFormDataContent();

    formContent.Add(new StringContent(model.PostTittle), "PostTittle");

    //...
    //for other properties, such as FileNameA, FileType etc
    //...

    formContent.Add(new StreamContent(model.ContentFile.OpenReadStream()), "ContentFile", Path.GetFileName(model.ContentFile.FileName));


    HttpClient hc = new HttpClient();
    hc.BaseAddress = new Uri("https://localhost:44325/api/Users/");

    var userPost = await hc.PostAsync("createPost", formContent);

    //...

API 操作

public async Task<IActionResult> createPost([FromForm]ForumThemeModel model) 
{
    //...

推荐阅读