下载excel文件并使用azure函数阅读内容

时间:2017-04-02 18:15:42

标签: azure azure-functions openxml-sdk azure-storage-files

我正在尝试使用OpenXml-SDK编写C#Azure函数来下载和打开Excel文件。

Office Interop无法在此处工作,因为Azure功能无法使用Office。

我正在尝试使用OpenXml-SDK打开并读取似乎需要保存文件路径的文件,而不是从远程网址下载的网址或流。

鉴于我不知道如何在Azure Functions中临时存储excel文件,我使用了Azure文件存储。

我将excel文件从网址上传到Azure文件存储,但我无法使用OpenXML-SDK打开excel文件。

我测试了Azure文件存储中的excel文件正在运行,但是,当我尝试打开一个MemoryStream的OpenXML.SpreadsheetDocument时,我收到错误,指示该文件已损坏。

如果我尝试打开传递文件Uri(https://docs.microsoft.com/en-us/azure/storage/storage-dotnet-how-to-use-files#develop-with-file-storage)的SpreadsheetDocument,则地址会超过260个字符的限制。

我打开使用OpenXML以外的库,理想情况下我不想存储excel文件。

2 个答案:

答案 0 :(得分:6)

Open XML SDK在Azure Function中运行良好。我测试了它在我身边。这是完整的代码。

#r "DocumentFormat.OpenXml.dll"
#r "WindowsBase.dll"

using System.Net;
using System.IO;
using DocumentFormat.OpenXml.Packaging;
using DocumentFormat.OpenXml.Spreadsheet;

public static HttpResponseMessage Run(HttpRequestMessage req, TraceWriter log)
{
    log.Info($"C# HTTP trigger function processed a request. RequestUri={req.RequestUri}");

    WebClient client = new WebClient();

    byte[] buffer = client.DownloadData("http://amor-webapp-test.azurewebsites.net/Content/hello.xlsx");
    MemoryStream stream = new MemoryStream();
    stream.Write(buffer, 0, buffer.Length);
    stream.Position = 0;
    using (SpreadsheetDocument doc = SpreadsheetDocument.Open(stream, false))
    {
        WorkbookPart workbookPart = doc.WorkbookPart;
        SharedStringTablePart sstpart = workbookPart.GetPartsOfType<SharedStringTablePart>().First();
        SharedStringTable sst = sstpart.SharedStringTable;

        WorksheetPart worksheetPart = workbookPart.WorksheetParts.First();
        Worksheet sheet = worksheetPart.Worksheet;

        var cells = sheet.Descendants<Cell>();
        var rows = sheet.Descendants<Row>();

        log.Info(string.Format("Row count = {0}", rows.LongCount()));
        log.Info(string.Format("Cell count = {0}", cells.LongCount()));

        // One way: go through each cell in the sheet
        foreach (Cell cell in cells)
        {
            if ((cell.DataType != null) && (cell.DataType == CellValues.SharedString))
            {
                int ssid = int.Parse(cell.CellValue.Text);
                string str = sst.ChildElements[ssid].InnerText;
                log.Info(string.Format("Shared string {0}: {1}", ssid, str));
            }
            else if (cell.CellValue != null)
            {
                log.Info(string.Format("Cell contents: {0}", cell.CellValue.Text));
            }
        }
    }

    return req.CreateResponse(HttpStatusCode.OK, "Hello ");
}

enter image description here

要使用Open XML,请确保在功能文件夹下创建了一个bin文件夹,并将DocumentFormat.OpenXml.dll和WindowsBase.dll上传到它。

  

“文件包含损坏的数据”。

您是否尝试过另一个Excel文件来检查问题是否与特定的Excel文件有关。我建议你创建一个新的简单excel来再次测试你的代码。

  

“它对我的文件无法使用相同的”文件包含损坏的数据“消息。”

我下载了你的excel文件,发现它是excel文件的旧版本(.xls)。

要修复异常,您可以将excel转换为最新版本(.xlsx)或选择其他excel解析库。 ExcelDataReader可以适用于任何版本的excel文件。您可以通过搜索“ExcelDataReader”使用NuGet安装此库。以下是如何解析.xls格式excel文件的示例代码。我在Azure Function上测试过,它确实运行良好。

#r "Excel.dll"
#r "System.Data"

using System.Net;
using System.IO;
using Excel;
using System.Data;

public static HttpResponseMessage Run(HttpRequestMessage req, TraceWriter log)
{
    log.Info($"C# HTTP trigger function processed a request. RequestUri={req.RequestUri}");

    WebClient client = new WebClient();

    byte[] buffer = client.DownloadData("http://amor-webapp-test.azurewebsites.net/Content/abcdefg.xls");
    MemoryStream stream = new MemoryStream();
    stream.Write(buffer, 0, buffer.Length);
    stream.Position = 0;

    IExcelDataReader excelReader = ExcelReaderFactory.CreateBinaryReader(stream);

    DataSet result = excelReader.AsDataSet();

    for (int i = 0; i < result.Tables.Count; i++)
    {
        log.Info(result.Tables[i].TableName +" has " + result.Tables[i].Rows.Count + " rows.");
    }

    return req.CreateResponse(HttpStatusCode.OK, "Hello ");
}

在执行上层代码之前,请将“Excel.dll”文件添加到函数的bin文件夹中。

答案 1 :(得分:3)

如果确实需要保存临时文件,Azure Functions会有一个%TEMP%环境变量,其中包含临时文件夹的路径。这是运行您的函数的vm的本地文件夹,不会被保留。

但是,无需在本地/ Azure文件中保存文件。您应该能够从响应中获取流请求并将其直接传递给OpenXML

HttpWebRequest request = (HttpWebRequest)WebRequest.Create(originalExcelUrl);
using (HttpWebResponse response = (HttpWebResponse)request.GetResponse())
using (Stream stream = response.GetResponseStream()) 
{
    var doc = SpreadsheetDocument.Open(stream, true);
    // etc
}