ASP.NET MVC 6中如何上传文件

5

我在ASP.NET MVC 6中上传文件/图片时遇到了麻烦。大多数教程似乎已经过时,即使一些新的教程也提到了一些不合理的东西。

在我的视图中:

<div class="form-group">
    @using (Html.BeginForm("Create", "PostNin", FormMethod.Post, new { enctype = "multipart/form-data" }))
    {
        <label asp-for="NinImageString" class="control-label"></label>
        <input type="file" name="files" class="form-control" />
    }

    @*<input asp-for="NinImageString" class="form-control" />
    <span asp-validation-for="NinImageString" class="text-danger"></span>*@
</div>
<div class="form-group">
    <label asp-for="NinImageCaption" class="control-label"></label>
    <input asp-for="NinImageCaption" class="form-control" />
    <span asp-validation-for="NinImageCaption" class="text-danger"></span>
</div>

然后在我的控制器中:

// GET: PostNins/Create
public IActionResult Create()
{
    return View();
}

[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Create([Bind("Id,NinFk,NinDigit,NinImageString,NinImageCaption,NinNote")] PostNin postNin, IFormFile files)
{
    // need code here
        
    if (ModelState.IsValid)
    {
        _context.Add(postNin);
        await _context.SaveChangesAsync();
        return RedirectToAction(nameof(Index));
    }

    return View(postNin);
}

我理解需要使用IFormFile来实现。

我想上传一张带标题的图片,并将其存储到应用程序文件夹NinImages中,以便稍后访问。 我想我也有关于它的问题,但这是另一个问题。

我的理解是,必须以某种方式将图像副本保存到目录系统中,在wwwroot下保存文件路径作为字符串到数据库中。

解决方案:

我的新控制器如下所示。请注意,fileTime仅用于为每个上传分配唯一值,以避免重复。 在这种情况下,这有效,因为只能上传一个文件。

[HttpPost]
    [ValidateAntiForgeryToken]
    public async Task<IActionResult> Create([Bind("Id,NinFk,NinDigit,NinImageString,NinImageCaption,NinNote")] PostNin postNin, IFormFile uploadFile)
    {


        if (uploadFile != null && uploadFile.Length > 0)
        {
            var fileTime = DateTime.UtcNow.ToString("yyMMddHHmmss");
            var fileName = fileTime + Path.GetFileName(uploadFile.FileName);
            var filePath = Path.Combine(Directory.GetCurrentDirectory(), "wwwroot/NinFileUploads", fileName);

            postNin.NinImageString = filePath;
            _context.PostNins.Add(postNin);
            _context.SaveChanges();

            using (var fileStream = new FileStream(filePath, FileMode.Create))
            {
                await uploadFile.CopyToAsync(fileStream);
            }
            //if (ModelState.IsValid)
            //{
            //    _context.Add(postNin);
            //    await _context.SaveChangesAsync();
            //    return RedirectToAction(nameof(Index));
            //}
            return RedirectToAction(nameof(Index));

        }
        return View(postNin);

4
这里的任何答案有帮助吗? https://dev59.com/uVsW5IYBdhLWcg3wHEHZ 如果没有,你得到了什么错误?我不知道这是否是一个打字错误,但是 enctype =“multipart/form-date” 是错误的,它应该是“multipart/form-data”。 - Jasen
笔误被你发现了,谢谢。它们中的一些是有帮助的,但不完整或者它们正在执行不同的操作。 - Nick Fleetwood
3个回答

4

这里是一个演示作品:

PostNin 类:

public class PostNin
    {
        public int Id { get; set; }
        public string Name { get; set; }
        public string ImagePath { get; set; }
    }

控制器:

public async Task<bool> Create(PostNin postNin,IFormFile upload)
        {     
                if (upload != null && upload.Length > 0)
                {                
                    var fileName = Path.GetFileName(upload.FileName);
                    var filePath = Path.Combine(Directory.GetCurrentDirectory(), "wwwroot/images", fileName);
                    postNin.ImagePath = filePath;
                    _context.PostNins.Add(postNin);
                    _context.SaveChanges();
                    using (var fileSrteam = new FileStream(filePath, FileMode.Create))
                    {
                        await upload.CopyToAsync(fileSrteam);
                    }
                    return true;
                }
                return false;
        }

结果: 在这里输入图片描述

哦,很接近了。你为什么使用“bool”而不是“IActionResult”?我尝试使用你的代码,但出现了一个错误,“找不到路径的一部分”。请参见更新的问题。 - Nick Fleetwood
这个完美地奏效了。谢谢。我有一个后续问题,关于上传文件的命名,这就是为什么我还没有标记为已回答的原因。我感谢你的帮助。同时,我想指出你的代码和图像非常详细和有帮助。 - Nick Fleetwood

2

您需要将输入元素的name属性设置为与Create方法参数相同,在此解决方案中,name属性和Create方法参数均设置为uploadFile

HTML

<input type="file" name="uploadFile" class="form-control" />

CS

Create([Bind("Id,NinFk,NinDigit,NinImageString,NinImageCaption,NinNote")] PostNin postNin, IFormFile uploadFile)

公正的观点。我已经进行了调整。接下来我该做什么? - Nick Fleetwood
标记旧问题的正确解决方案,并为下一个问题创建新的解决方案。 - Saeed Gholamzadeh

1
将文件上传控件的名称更改为“files”。
<input type="file" name="files" class="form-control" />

在IFormFile文件之前加上[FromForm],然后尝试是否有效

Create([Bind("Id,NinFk,NinDigit,NinImageString,NinImageCaption,NinNote")] PostNin postNin, [FromForm]IFormFile files)

如果不起作用,请尝试将新的IFormFile文件属性添加到PostNin类中,或创建一个新的类作为此操作的模型,并在动作参数之前添加[FromForm]。

public class PostNinModel {
....
public IFormFile files { get; set; }
...
}

Create([FromForm] PostNinModel postNin)

1
我已更新文件上传控件并在操作参数上添加了[FromForm]。没有IDE错误。但现在怎么办?我该如何“尝试它”? - Nick Fleetwood
文件已发送到操作了吗?您可以使用断点进行检查,然后可以保存该文件。请参阅以下链接了解详细信息:https://dev59.com/ilkS5IYBdhLWcg3w5KEi - fligant

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接