将 excelsheet 发送到 azure function 进行处理
send excelsheet to azure function for processing
在我们当前的项目中,我们希望用户能够在我们的网站上上传 excel 文件,并且应该处理那些 excel sheets(读取每一行并存储它们在数据库中)使用 Azure 函数。
此功能过去位于我们的 .Net Core MVC 项目的后端,使用接受 IFormFile
参数的 Task<IActionResult>
post 方法。 sheet 已处理(读取所有行)。
但是,Azure 函数似乎不接受 IFormFile 参数。我的问题是如何将此 excelsheet 数据添加到请求中?
这是来自 Web 应用程序的 post
方法,可激活 azure 功能:
[HttpPost]
public async Task<ActionResult> Bulkimport(IFormFile excelsheet)
{
string azFunctionUri = "https://azfunctionsUri.azurewebsites.net";
if (customerExists)
{
using (MemoryStream ms = new MemoryStream())
{
await excelsheet.CopyToAsync(ms).ConfigureAwait(false);
string content = Encoding.ASCII.GetString(ms.ToArray());
// use content as parameter in api builder method
IApiBuilder apiBuilder = new ApiBuilder();
HttpResponseMessage buildRequest = await apiBuilder.BuildFileRequest(azFunctionUri, content); // This builds the request and sends it to the azure function.
}
}
return View();
}
BuildFileRequest.cs(构造请求的辅助方法):
public async Task<HttpResponseMessage> BuildFileRequest(string uri, string content)
{
MultipartFormDataContent multiContent = new MultipartFormDataContent();
byte[] payload = Encoding.UTF8.GetBytes(content);
multiContent.Add(new ByteArrayContent(payload), "files"); // name must be "files"
HttpResponseMessage response = await httpClient.PostAsync($"{uri}", multiContent).ConfigureAwait(false);
return response;
}
我一直纠结于如何在函数中接收此请求并根据请求构建 excel 文件,以便可以在数据库中读取和处理行。
根据我的测试,我们可以使用下面的代码接收excel文件
- 客户端代码。这是我的测试 xlsx 文件
using (var httpClient = new HttpClient())
{
using (var form = new MultipartFormDataContent())
{
using (var fs = File.OpenRead(filePath))
{
using (var streamContent = new StreamContent(fs))
{
using (var fileContent = new ByteArrayContent(await streamContent.ReadAsByteArrayAsync()))
{
fileContent.Headers.ContentType = MediaTypeHeaderValue.Parse("multipart/form-data");
form.Add(fileContent, "file", Path.GetFileName(filePath));
HttpResponseMessage response = await httpClient.PostAsync(url, form);
}
}
}
}
}
- Azure 函数
public static async Task<IActionResult> Run(
[HttpTrigger(AuthorizationLevel.Anonymous, "get", "post", Route = null)] HttpRequest req,
ILogger log)
{
log.LogInformation("C# HTTP trigger function processed a request.");
foreach (var file in req.Form.Files) {
//Process excel file
/* For example use sdk : DocumentFormat.OpenXml.
For more details, please refer to https://docs.microsoft.com/en-us/office/open-xml/how-to-parse-and-read-a-large-spreadsheet
*/
using (var stream = new MemoryStream()) {
await file.CopyToAsync(stream);
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.LogInformation(string.Format("Row count = {0}", rows.LongCount()));
log.LogInformation(string.Format("Cell count = {0}", cells.LongCount()));
}
}
}
return new OkObjectResult("Ok")
}
在我们当前的项目中,我们希望用户能够在我们的网站上上传 excel 文件,并且应该处理那些 excel sheets(读取每一行并存储它们在数据库中)使用 Azure 函数。
此功能过去位于我们的 .Net Core MVC 项目的后端,使用接受 IFormFile
参数的 Task<IActionResult>
post 方法。 sheet 已处理(读取所有行)。
但是,Azure 函数似乎不接受 IFormFile 参数。我的问题是如何将此 excelsheet 数据添加到请求中?
这是来自 Web 应用程序的 post
方法,可激活 azure 功能:
[HttpPost]
public async Task<ActionResult> Bulkimport(IFormFile excelsheet)
{
string azFunctionUri = "https://azfunctionsUri.azurewebsites.net";
if (customerExists)
{
using (MemoryStream ms = new MemoryStream())
{
await excelsheet.CopyToAsync(ms).ConfigureAwait(false);
string content = Encoding.ASCII.GetString(ms.ToArray());
// use content as parameter in api builder method
IApiBuilder apiBuilder = new ApiBuilder();
HttpResponseMessage buildRequest = await apiBuilder.BuildFileRequest(azFunctionUri, content); // This builds the request and sends it to the azure function.
}
}
return View();
}
BuildFileRequest.cs(构造请求的辅助方法):
public async Task<HttpResponseMessage> BuildFileRequest(string uri, string content)
{
MultipartFormDataContent multiContent = new MultipartFormDataContent();
byte[] payload = Encoding.UTF8.GetBytes(content);
multiContent.Add(new ByteArrayContent(payload), "files"); // name must be "files"
HttpResponseMessage response = await httpClient.PostAsync($"{uri}", multiContent).ConfigureAwait(false);
return response;
}
我一直纠结于如何在函数中接收此请求并根据请求构建 excel 文件,以便可以在数据库中读取和处理行。
根据我的测试,我们可以使用下面的代码接收excel文件
- 客户端代码。这是我的测试 xlsx 文件
using (var httpClient = new HttpClient())
{
using (var form = new MultipartFormDataContent())
{
using (var fs = File.OpenRead(filePath))
{
using (var streamContent = new StreamContent(fs))
{
using (var fileContent = new ByteArrayContent(await streamContent.ReadAsByteArrayAsync()))
{
fileContent.Headers.ContentType = MediaTypeHeaderValue.Parse("multipart/form-data");
form.Add(fileContent, "file", Path.GetFileName(filePath));
HttpResponseMessage response = await httpClient.PostAsync(url, form);
}
}
}
}
}
- Azure 函数
public static async Task<IActionResult> Run(
[HttpTrigger(AuthorizationLevel.Anonymous, "get", "post", Route = null)] HttpRequest req,
ILogger log)
{
log.LogInformation("C# HTTP trigger function processed a request.");
foreach (var file in req.Form.Files) {
//Process excel file
/* For example use sdk : DocumentFormat.OpenXml.
For more details, please refer to https://docs.microsoft.com/en-us/office/open-xml/how-to-parse-and-read-a-large-spreadsheet
*/
using (var stream = new MemoryStream()) {
await file.CopyToAsync(stream);
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.LogInformation(string.Format("Row count = {0}", rows.LongCount()));
log.LogInformation(string.Format("Cell count = {0}", cells.LongCount()));
}
}
}
return new OkObjectResult("Ok")
}