【问题标题】:Read an Excel file uploaded using FileUpload Control without saving it on the server读取使用 FileUpload Control 上传的 Excel 文件,而不将其保存在服务器上
【发布时间】:2012-09-07 08:53:09
【问题描述】:

需要能够读取在 ASP.NET 中使用 FileUploadControl 上传的 Excel 文件。该解决方案将托管在服务器上。我不想将 Excel 文件存储在服务器上。 我想直接将excel内容转换成数据集或者数据表来使用。

以下是我已经找到但不适用于我的两个解决方案。

  1. LINQTOEXCEL - 当您在本地计算机上有一个 excel 文件并且您在本地计算机上运行代码时,此方法有效。在我的例子中,用户正在尝试使用服务器上托管的网页从他的本地机器上传一个 excel 文件。

  2. ExcelDataReader - 我目前正在使用这个,但这是第三方工具。我不能把它转给我们的客户。此外,如果行/列交叉点带有公式,则不会将该行/列交叉点的数据读入数据集中。

当 excel 和 .NET 解决方案在同一台机器上时,我在 google 和 StackOverflow 上找到的大多数建议都有效。但是在我的情况下,当解决方案托管在服务器上并且用户尝试使用本地计算机上的托管网页上传 excel 时,我需要它来工作。 如果您有其他建议,可以告诉我吗?

【问题讨论】:

    标签: c# .net vb.net excel file-upload


    【解决方案1】:

    您可以使用HttpPostedFileInputStream 属性将文件读入内存。

    下面的示例展示了如何使用 EPPlusIO.StreamIO.Stream 创建DataTable

    protected void UploadButton_Click(Object sender, EventArgs e)
    {
        if (FileUpload1.HasFile && Path.GetExtension(FileUpload1.FileName) == ".xlsx")
        {
            using (var excel = new ExcelPackage(FileUpload1.PostedFile.InputStream))
            {
                var tbl = new DataTable();
                var ws = excel.Workbook.Worksheets.First();
                var hasHeader = true;  // adjust accordingly
                // add DataColumns to DataTable
                foreach (var firstRowCell in ws.Cells[1, 1, 1, ws.Dimension.End.Column])
                    tbl.Columns.Add(hasHeader ? firstRowCell.Text
                        : String.Format("Column {0}", firstRowCell.Start.Column));
    
                // add DataRows to DataTable
                int startRow = hasHeader ? 2 : 1;
                for (int rowNum = startRow; rowNum <= ws.Dimension.End.Row; rowNum++)
                {
                    var wsRow = ws.Cells[rowNum, 1, rowNum, ws.Dimension.End.Column];
                    DataRow row = tbl.NewRow();
                    foreach (var cell in wsRow)
                        row[cell.Start.Column - 1] = cell.Text;
                    tbl.Rows.Add(row);
                }
                var msg = String.Format("DataTable successfully created from excel-file. Colum-count:{0} Row-count:{1}",
                                        tbl.Columns.Count, tbl.Rows.Count);
                UploadStatusLabel.Text = msg;
            }
        }
        else 
        {
            UploadStatusLabel.Text = "You did not specify a file to upload.";
        }
    }
    

    这是 VB.NET 版本

    Sub UploadButton_Click(ByVal sender As Object, ByVal e As System.EventArgs)
        If (FileUpload1.HasFile AndAlso IO.Path.GetExtension(FileUpload1.FileName) = ".xlsx") Then
            Using excel = New ExcelPackage(FileUpload1.PostedFile.InputStream)
                Dim tbl = New DataTable()
                Dim ws = excel.Workbook.Worksheets.First()
                Dim hasHeader = True ' change it if required '
                ' create DataColumns '
                For Each firstRowCell In ws.Cells(1, 1, 1, ws.Dimension.End.Column)
                    tbl.Columns.Add(If(hasHeader,
                                       firstRowCell.Text,
                                       String.Format("Column {0}", firstRowCell.Start.Column)))
                Next
                ' add rows to DataTable '
                Dim startRow = If(hasHeader, 2, 1)
                For rowNum = startRow To ws.Dimension.End.Row
                    Dim wsRow = ws.Cells(rowNum, 1, rowNum, ws.Dimension.End.Column)
                    Dim row = tbl.NewRow()
                    For Each cell In wsRow
                        row(cell.Start.Column - 1) = cell.Text
                    Next
                    tbl.Rows.Add(row)
                Next
                Dim msg = String.Format("DataTable successfully created from excel-file Colum-count:{0} Row-count:{1}",
                                        tbl.Columns.Count, tbl.Rows.Count)
                UploadStatusLabel.Text = msg
            End Using
        Else
            UploadStatusLabel.Text = "You did not specify an excel-file to upload."
        End If
    End Sub
    

    为了完整起见,这里是aspx:

    <div>
       <h4>Select a file to upload:</h4>
    
       <asp:FileUpload id="FileUpload1"                 
           runat="server">
       </asp:FileUpload>
    
       <br /><br />
    
       <asp:Button id="UploadButton" 
           Text="Upload file"
           OnClick="UploadButton_Click"
           runat="server">
       </asp:Button>    
    
       <hr />
    
       <asp:Label id="UploadStatusLabel"
           runat="server">
       </asp:Label>        
    </div>
    

    【讨论】:

    • 嗨蒂姆,感谢您的快速回复。我相信这需要在托管服务器上安装 Microsoft Office。如果是,请告诉我是否还有其他解决方法?如果没有,那么没有问题。我会对此进行测试并通知您。
    • @Chandra:如前所述,我正在使用EPPLus,它在LGPL license 下是免费的。我可以热情地推荐它,而且我不是唯一一个。 stackoverflow.com/a/2603625/284240(在接受的 Jan 本身旁边)
    • 感谢您的快速回复!我看到这是开源代码,很难将其推送给我们的知名客户。是否可以使用纯 .NET 代码来实现这一点?
    • 可能因为你用的是旧的xls文件,EPPlus只支持xlsx
    • @StaticVoid:那么您使用的是 .NET 2 或者您没有添加 using System.Linq。除此之外,第一个工作表是excel.Workbook.Worksheets[0]。这也是我喜欢First的原因,它更具可读性。
    【解决方案2】:
    //Best Way To read file direct from stream
    IExcelDataReader excelReader = null;
    //file.InputStream is the file stream stored in memeory by any ways like by upload file control or from database
    int excelFlag = 1; //this flag us used for execl file format .xls or .xlsx
    if (excelFlag == 1)
    {
        //1. Reading from a binary Excel file ('97-2003 format; *.xls)
        excelReader = ExcelReaderFactory.CreateBinaryReader(file.InputStream);
    }
    else if(excelFlag == 2)                                
    {
        //2. Reading from a OpenXml Excel file (2007 format; *.xlsx)
        excelReader = ExcelReaderFactory.CreateOpenXmlReader(file.InputStream);
    }
    
    if (excelReader != null)
    {
        //...
        //3. DataSet - The result of each spreadsheet will be created in the result.Tables
        ds = excelReader.AsDataSet();
        //...
        ////4. DataSet - Create column names from first row
        //excelReader.IsFirstRowAsColumnNames = true;
        //DataSet result = excelReader.AsDataSet();
    
        ////5. Data Reader methods
        //while (excelReader.Read())
        //{
        //    //excelReader.GetInt32(0);
        //}
    
        //6. Free resources (IExcelDataReader is IDisposable)
        excelReader.Close();
    }
    

    【讨论】:

      【解决方案3】:

      这是在 MVC 中使用 ClosedXML.Excel 执行此操作的方法。我知道这个答案为时已晚。我只是想为所有在谷歌搜索问题后登陆此页面的人提供这个答案。在 Visual Studio 中单击工具菜单并展开 NuGet 包管理器,然后运行包管理器控制台。键入以下命令:

      Install-Package ClosedXML
      

      模型:

      namespace ExcelUploadFileDemo.Models
          {
              public class UploadFile
              {
                  [Required]
                  public HttpPostedFileBase ExcelFile { get; set; }
              }
          }
      

      控制器:

      namespace ExcelUploadFileDemo.Controllers
          {
              public class HomeController : Controller
              {
                  public ActionResult Index()
                  {
                      UploadFile UploadFile = new UploadFile();
                      return View(UploadFile);
                  }
      
                  [HttpPost]
                  public ActionResult Index(UploadFile UploadFile)
                  {
                      if (ModelState.IsValid)
                      {
      
                          if (UploadFile.ExcelFile.ContentLength > 0)
                          {
                              if (UploadFile.ExcelFile.FileName.EndsWith(".xlsx") || UploadFile.ExcelFile.FileName.EndsWith(".xls"))
                              {
                                  XLWorkbook Workbook;
                                  Try//incase if the file is corrupt
                                  {
                                      Workbook = new XLWorkbook(UploadFile.ExcelFile.InputStream);
                                  }
                                  catch (Exception ex)
                                  {
                                      ModelState.AddModelError(String.Empty, $"Check your file. {ex.Message}");
                                      return View();
                                  }
                                  IXLWorksheet WorkSheet = null;
                                  Try//incase if the sheet you are looking for is not found
                                  {
                                      WorkSheet = Workbook.Worksheet("sheet1");
      
                                  }
                                  catch
                                  {
                                      ModelState.AddModelError(String.Empty, "sheet1 not found!");
                                      return View();
                                  }
                                  WorkSheet.FirstRow().Delete();//if you want to remove ist row
      
                                  foreach (var row in WorkSheet.RowsUsed())
                                  {
                                      //do something here
                                      row.Cell(1).Value.ToString();//Get ist cell. 1 represent column number
      
                                  }
                              }
                              else
                              {
                                  ModelState.AddModelError(String.Empty, "Only .xlsx and .xls files are allowed");
                                  return View();
                              }
                          }
                          else
                          {
                              ModelState.AddModelError(String.Empty, "Not a valid file");
                              return View();
                          }
                      }
                      return View();
                  }
              }
          }
      

      此链接有许多示例,展示了处理各种 excel 内容的不同方法。

      https://github.com/ClosedXML/ClosedXML/tree/9ac4d868a313f308b82e94617b9cc2d28baeb1c3/ClosedXML

      观点

      @model ExcelUploadFileDemo.Models.UploadFile
      
      
      @{
          ViewBag.Title = "Upload Excel File";
      }
      <h2>Upload an Excel File</h2>
      
      @using (Html.BeginForm(null, null, FormMethod.Post, new { enctype = "multipart/form-data" }))
      {
      
      
      
          <div class="form-horizontal">
              @Html.ValidationSummary("", new { @class = "text-danger" });
              <div class="form-group">
                  @Html.LabelFor(model => model.ExcelFile, htmlAttributes: new { @class = "control-label col-md-2" })
                  <div class="col-md-10">
                      @Html.TextBoxFor(model => model.ExcelFile, new { type = "file", @class = "form-control" })
                      @Html.ValidationMessageFor(model => model.ExcelFile, "", new { @class = "text-danger" })
                  </div>
              </div>
              <div class="form-group">
                  <div class="col-md-offset-2 col-md-10">
                      <input type = "submit" value="Submit" class="btn btn-default" />
                  </div>
              </div>
        </div>
      }
      

      【讨论】:

        【解决方案4】:

        也许你可以看看Koogra这是一个开源excel阅读器(只读没有作家)我想你会从客户端得到一个流。然后你可以像现在一样做所有的事情从内存流中读取并写入数据库。

        我希望这会有所帮助。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2010-10-08
          • 1970-01-01
          • 2015-03-02
          • 2021-03-29
          • 2011-03-26
          • 1970-01-01
          相关资源
          最近更新 更多