下载 excel 文件并使用 azure 函数读取内容
Download an excel file and read content with azure functions
我正在尝试编写一个 C# Azure 函数来使用 OpenXml-SDK 下载并打开一个 excel 文件。
Office Interop 在这里不起作用,因为 Office 不适用于 Azure Functions。
我正在尝试使用 OpenXml-SDK 打开和读取文件,该文件似乎需要保存文件的路径,而不是 url 或从远程 url 下载的流。
鉴于我不知道在 Azure Functions 中临时存储 excel 文件的方法,我使用了 Azure 文件存储。
我将 excel 文件从 url 上传到 Azure 文件存储,但是我无法使用 OpenXML-SDK 打开 excel 文件。
我测试了 Azure 文件存储中的 excel 文件是否正常工作,但是,当我尝试打开 OpenXML.SpreadsheetDocument 表单 MemoryStream 时,我收到错误消息,指示文件已损坏。
如果我尝试打开传递文件 Uri (https://docs.microsoft.com/en-us/azure/storage/storage-dotnet-how-to-use-files#develop-with-file-storage) 的 SpreadsheetDocument,则地址超过了 260 个字符的限制。
我愿意使用 OpenXML 以外的库,理想情况下我宁愿不必存储 excel 文件。
如果您确实需要保存临时文件,Azure Functions 有一个 %TEMP%
环境变量,其中包含临时文件夹的路径。这是运行您的函数的虚拟机的本地文件夹,不会保留。
但是,无需将文件保存在本地/Azure 文件中。您应该能够从对 get 请求的响应中获取流并将其直接传递给 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
}
打开 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 ");
}
要使用 Open XML,请确保您已经在您的函数文件夹下创建了一个 bin 文件夹并上传了 DocumentFormat.OpenXml.dll 和 WindowsBase.dll。
"File contains corrupted data".
您是否尝试过另一个 excel 文件来检查问题是否与特定的 excel 文件有关。我建议您创建一个新的简单 excel 来再次测试您的代码。
"It didn't work on my file with the same "File contains corrupted data" message. "
我下载了您的 excel 文件,发现它是 excel 文件的旧版本 (.xls)。
要修复异常,您可以将 excel 转换为最新版本 (.xlsx) 或选择另一个 excel 解析库。 ExcelDataReader 适用于任何版本的 excel 文件。您可以通过搜索 'ExcelDataReader' 使用 NuGet 安装此库。以下是如何解析 .xls 格式 excel 文件的示例代码。我在 Azure Functions 上测试过,它确实运行良好。
#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文件夹中。
我正在尝试编写一个 C# Azure 函数来使用 OpenXml-SDK 下载并打开一个 excel 文件。
Office Interop 在这里不起作用,因为 Office 不适用于 Azure Functions。
我正在尝试使用 OpenXml-SDK 打开和读取文件,该文件似乎需要保存文件的路径,而不是 url 或从远程 url 下载的流。
鉴于我不知道在 Azure Functions 中临时存储 excel 文件的方法,我使用了 Azure 文件存储。
我将 excel 文件从 url 上传到 Azure 文件存储,但是我无法使用 OpenXML-SDK 打开 excel 文件。
我测试了 Azure 文件存储中的 excel 文件是否正常工作,但是,当我尝试打开 OpenXML.SpreadsheetDocument 表单 MemoryStream 时,我收到错误消息,指示文件已损坏。
如果我尝试打开传递文件 Uri (https://docs.microsoft.com/en-us/azure/storage/storage-dotnet-how-to-use-files#develop-with-file-storage) 的 SpreadsheetDocument,则地址超过了 260 个字符的限制。
我愿意使用 OpenXML 以外的库,理想情况下我宁愿不必存储 excel 文件。
如果您确实需要保存临时文件,Azure Functions 有一个 %TEMP%
环境变量,其中包含临时文件夹的路径。这是运行您的函数的虚拟机的本地文件夹,不会保留。
但是,无需将文件保存在本地/Azure 文件中。您应该能够从对 get 请求的响应中获取流并将其直接传递给 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
}
打开 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 ");
}
要使用 Open XML,请确保您已经在您的函数文件夹下创建了一个 bin 文件夹并上传了 DocumentFormat.OpenXml.dll 和 WindowsBase.dll。
"File contains corrupted data".
您是否尝试过另一个 excel 文件来检查问题是否与特定的 excel 文件有关。我建议您创建一个新的简单 excel 来再次测试您的代码。
"It didn't work on my file with the same "File contains corrupted data" message. "
我下载了您的 excel 文件,发现它是 excel 文件的旧版本 (.xls)。
要修复异常,您可以将 excel 转换为最新版本 (.xlsx) 或选择另一个 excel 解析库。 ExcelDataReader 适用于任何版本的 excel 文件。您可以通过搜索 'ExcelDataReader' 使用 NuGet 安装此库。以下是如何解析 .xls 格式 excel 文件的示例代码。我在 Azure Functions 上测试过,它确实运行良好。
#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文件夹中。