(前言:这个问题是关于2011年发布的ASP.NET MVC 3.0,而不是关于2019年发布的ASP.NETCore 3.0)

我想用asp.net mvc上传文件。如何使用html输入文件控件上载文件?


当前回答

尽管我在donnetfiddle上为你做了一个示例项目,但大多数答案似乎都足够合理

我正在使用LumenWorks.Framework进行CSV工作,但这不是必须的。

Demo

View

            @using (Html.BeginForm("Index", "Home", "POST")) 

            {
                <div class="form-group">

                        <label for="file">Upload Files:</label>
                        <input type="file" multiple name="files" id="files" class="form-control"/><br><br>
                        <input type="submit" value="Upload Files" class="form-control"/>
                </div>

控制器:

    [HttpPost]
    public ActionResult Index(HttpPostedFileBase upload)
    {
        if (ModelState.IsValid)
        {
            if (upload != null && upload.ContentLength > 0)
            {
                // Validation content length 
                if (upload.FileName.EndsWith(".csv") || upload.FileName.EndsWith(".CSV"))
                {
                    //extention validation 
                    ViewBag.Result = "Correct File Uploaded";
                }
            }
        }

        return View();
    }

其他回答

如果你碰巧像我一样在这里跌跌撞撞,想知道尽管代码正确,为什么你的代码仍然不工作。然后,请在输入控件中查找name属性,您可能会意外错过或从未将其放在首位。

<input class="custom-file-input" name="UploadFile" id="UploadFile" type="file" onchange="ValidateFile(this);" accept=".xls, .xlsx">
                             

在视图中:

<form action="Categories/Upload" enctype="multipart/form-data" method="post">
    <input type="file" name="Image">
    <input type="submit" value="Save">
</form>

而控制器中的以下代码:

public ActionResult Upload()
{
    foreach (string file in Request.Files)
    {
       var hpf = this.Request.Files[file];
       if (hpf.ContentLength == 0)
       {
            continue;
       }

       string savedFileName = Path.Combine(
                AppDomain.CurrentDomain.BaseDirectory, "PutYourUploadDirectoryHere");
                savedFileName = Path.Combine(savedFileName, Path.GetFileName(hpf.FileName));

        hpf.SaveAs(savedFileName);
    }

    ...
}

通常,您还希望传递一个视图模型,而不仅仅是一个文件。在下面的代码中,您将发现一些其他有用的功能:

检查文件是否已附加检查文件大小是否为0检查文件大小是否大于4 MB检查文件大小是否小于100字节检查文件扩展名

可以通过以下代码完成:

[HttpPost]
public ActionResult Index(MyViewModel viewModel)
{
    // if file's content length is zero or no files submitted

    if (Request.Files.Count != 1 || Request.Files[0].ContentLength == 0)
    {
        ModelState.AddModelError("uploadError", "File's length is zero, or no files found");
        return View(viewModel);
    }

    // check the file size (max 4 Mb)

    if (Request.Files[0].ContentLength > 1024 * 1024 * 4)
    {
        ModelState.AddModelError("uploadError", "File size can't exceed 4 MB");
        return View(viewModel);
    }

    // check the file size (min 100 bytes)

    if (Request.Files[0].ContentLength < 100)
    {
        ModelState.AddModelError("uploadError", "File size is too small");
        return View(viewModel);
    }

    // check file extension

    string extension = Path.GetExtension(Request.Files[0].FileName).ToLower();

    if (extension != ".pdf" && extension != ".doc" && extension != ".docx" && extension != ".rtf" && extension != ".txt")
    {
        ModelState.AddModelError("uploadError", "Supported file extensions: pdf, doc, docx, rtf, txt");
        return View(viewModel);
    }

    // extract only the filename
    var fileName = Path.GetFileName(Request.Files[0].FileName);

    // store the file inside ~/App_Data/uploads folder
    var path = Path.Combine(Server.MapPath("~/App_Data/uploads"), fileName);

    try
    {
        if (System.IO.File.Exists(path))
            System.IO.File.Delete(path);

        Request.Files[0].SaveAs(path);
    }
    catch (Exception)
    {
        ModelState.AddModelError("uploadError", "Can't save file to disk");
    }

    if(ModelState.IsValid)
    {
        // put your logic here

        return View("Success");
    }

    return View(viewModel);         
}

确保你有

@Html.ValidationMessage("uploadError")

在您的视图中查看验证错误。

还要记住,默认最大请求长度为4MB(maxRequestLength=4096),要上载更大的文件,必须在web.config中更改此参数:

<system.web>
    <httpRuntime maxRequestLength="40960" executionTimeout="1100" />

(此处40960=40 MB)。

执行超时是秒的整数。您可能希望将其更改为允许上传大量文件。

另一种传输到字节[]的方法(用于保存到DB)。

@Arthur的方法工作得很好,但不能完美复制,因此MS Office文档在从数据库检索后可能无法打开。MemoryStream.GetBuffer()可以在字节[]的末尾返回额外的空字节,但可以使用MemoryStream.ToArray()来解决这个问题。然而,我发现这个替代方案可以完美地适用于所有文件类型:

using (var binaryReader = new BinaryReader(file.InputStream))
{
    byte[] array = binaryReader.ReadBytes(file.ContentLength);
}

这是我的完整代码:

文档类别:

public class Document
{
    public int? DocumentID { get; set; }
    public string FileName { get; set; }
    public byte[] Data { get; set; }
    public string ContentType { get; set; }
    public int? ContentLength { get; set; }

    public Document()
    {
        DocumentID = 0;
        FileName = "New File";
        Data = new byte[] { };
        ContentType = "";
        ContentLength = 0;
    }
}

文件下载:

[HttpGet]
public ActionResult GetDocument(int? documentID)
{
    // Get document from database
    var doc = dataLayer.GetDocument(documentID);

    // Convert to ContentDisposition
    var cd = new System.Net.Mime.ContentDisposition
    {
        FileName = doc.FileName, 

        // Prompt the user for downloading; set to true if you want 
        // the browser to try to show the file 'inline' (display in-browser
        // without prompting to download file).  Set to false if you 
        // want to always prompt them to download the file.
        Inline = true, 
    };
    Response.AppendHeader("Content-Disposition", cd.ToString());

    // View document
    return File(doc.Data, doc.ContentType);
}

文件上载:

[HttpPost]
public ActionResult GetDocument(HttpPostedFileBase file)
{
    // Verify that the user selected a file
    if (file != null && file.ContentLength > 0)
    {
        // Get file info
        var fileName = Path.GetFileName(file.FileName);
        var contentLength = file.ContentLength;
        var contentType = file.ContentType;

        // Get file data
        byte[] data = new byte[] { };
        using (var binaryReader = new BinaryReader(file.InputStream))
        {
            data = binaryReader.ReadBytes(file.ContentLength);
        }

        // Save to database
        Document doc = new Document()
        {
            FileName = fileName,
            Data = data,
            ContentType = contentType,
            ContentLength = contentLength,
        };
        dataLayer.SaveDocument(doc);

        // Show success ...
        return RedirectToAction("Index");
    }
    else
    {
        // Show error ...
        return View("Foo");
    }
}

视图(代码段):

@using (Html.BeginForm("GetDocument", "Home", FormMethod.Post, new { enctype = "multipart/form-data" }))
{
    <input type="file" name="file" />
    <input type="submit" value="Upload File" />
}

保存多个文件的简单方法

cshtml

@using (Html.BeginForm("Index","Home",FormMethod.Post,new { enctype = "multipart/form-data" }))
{
    <label for="file">Upload Files:</label>
    <input type="file" multiple name="files" id="files" /><br><br>
    <input type="submit" value="Upload Files" />
    <br><br>
    @ViewBag.Message
}

控制器

[HttpPost]
        public ActionResult Index(HttpPostedFileBase[] files)
        {
            foreach (HttpPostedFileBase file in files)
            {
                if (file != null && file.ContentLength > 0)
                    try
                    {
                        string path = Path.Combine(Server.MapPath("~/Files"), Path.GetFileName(file.FileName));
                        file.SaveAs(path);
                        ViewBag.Message = "File uploaded successfully";
                    }
                    catch (Exception ex)
                    {
                        ViewBag.Message = "ERROR:" + ex.Message.ToString();
                    }

                else
                {
                    ViewBag.Message = "You have not specified a file.";
                }
            }
            return View();
        }