在用户的下载文件夹中保存 excel 文件产生错误(.NET Core Razor Pages)
Saving excel file in user's downloads folder producing error (.NET Core Razor Pages)
在我的剃须刀页面应用程序中,我有一个按钮,您可以单击该按钮创建一个 excel 文件,并且应该会自动将其保存到您的下载文件夹中。
下面的代码在本地主机上运行良好 - 我点击按钮,它保存到我的下载文件夹,我可以查看它。
但是,在我发布并尝试后,我收到一条错误消息,指出 "Could not find a part of the path 'C:\WINDOWS\system32\config\systemprofile\Downloads\PartCommentHistory.xlsx'."。
我也完全可以更改此代码,而不是拉出保存文件对话框 window 并允许用户首先选择文件的保存位置 - 但我不确定如何. Google 没有太大帮助,所以我们来了!
如果我实际导航到此路径,我会注意到没有 Downloads 文件夹。我尝试在我的代码中添加一个 if 语句,说明如果此处不存在 Downloads 文件夹,请先创建它,然后将文件保存在那里。但是,这会产生另一个错误,即我无权访问该路径。
public async Task<IActionResult> OnPostExportAsync(string currentFilter)
{
string sFilePath = Path.Combine(Environment.ExpandEnvironmentVariables("%USERPROFILE%"),"Downloads");
string sFileName = @"PartCommentHistory.xlsx";
string URL = string.Format("{0}://{1}/{2}", Request.Scheme, Request.Host, sFileName);
FileInfo file = new FileInfo(Path.Combine(sFilePath, sFileName));
var memory = new MemoryStream();
using (var fs = new FileStream(Path.Combine(sFilePath, sFileName), FileMode.Create, FileAccess.Write))
{
ExcelPackage pck = new ExcelPackage();
ExcelWorksheet ws = pck.Workbook.Worksheets.Add("Worksheet1");
List<CmtPartComment> commentlist = _context.CmtPartComments.Select(x => new CmtPartComment
{
SupplierNo = x.SupplierNo,
PartNo = x.PartNo,
Comment = x.Comment,
EnterBy = x.EnterBy,
EnteredDt = x.EnterDt.ToString("yyyy-MM-dd HH:mm:ss tt"),
CompletedDt = x.CompleteDt.ToString("yyyy-MM-dd HH:mm:ss tt")
}).Include(c => c.System).OrderByDescending(x => x.EnterDt).Where(x => x.PartNo == currentFilter).ToList();
ws.Cells[1, 1].Value = "SupplierNo";
ws.Cells[1, 2].Value = "PartNo";
ws.Cells[1, 3].Value = "Comment";
ws.Cells[1, 4].Value = "EnterBy";
ws.Cells[1, 5].Value = "EnterDt";
ws.Cells[1, 6].Value = "CompleteDt";
int recordIndex = 2;
foreach (var item in commentlist)
{
ws.Cells[recordIndex, 1].Value = item.SupplierNo;
ws.Cells[recordIndex, 2].Value = item.PartNo;
ws.Cells[recordIndex, 3].Value = item.Comment;
ws.Cells[recordIndex, 4].Value = item.EnterBy;
ws.Cells[recordIndex, 5].Value = item.EnteredDt;
ws.Cells[recordIndex, 6].Value = item.CompletedDt;
recordIndex++;
}
ws.Cells["A:AZ"].AutoFitColumns();
pck.SaveAs(fs);
}
using (var stream = new FileStream(Path.Combine(sFilePath, sFileName), FileMode.Open))
{
await stream.CopyToAsync(memory);
}
memory.Position = 0;
return File(memory, "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", sFileName);
}
您无法确定文件在客户端计算机上的保存位置。它似乎在您的机器上工作的唯一原因是因为您的机器充当服务器。您所能做的就是在用户下载文件时强制出现“保存”或“打开”对话框,这是通过将内容类型设置为 application/octet-stream
来实现的:
Do I need Content-Type: application/octet-stream for file download?
使用此方法获取文件夹路径
Environment.GetFolderPath(Environment.SpecialFolder.Yourspecialfoldernamehere, System.Environment.SpecialFolderOption.None)
例如
Environment.GetFolderPath(Environment.SpecialFolder.System));
在上面的例子中系统是一个特殊的文件夹。
对于您的问题,这是由于您通过 using (var fs = new FileStream(Path.Combine(sFilePath, sFileName), FileMode.Create, FileAccess.Write))
在服务器端创建了一个临时文件,该文件在服务器端可能不存在。
根据您的要求,您正在尝试创建一个文件并将其 return 发送到客户端。如果是这样,则无需在服务器端创建本地文件,您可以 return 文件的字节如下所示:
public async Task<IActionResult> OnPostExportByInMemoryAsync(string currentFilter)
{
string sFileName = @"PartCommentHistory.xlsx";
using (var pck = new ExcelPackage())
{
ExcelWorksheet ws = pck.Workbook.Worksheets.Add("Worksheet1");
ws.Cells[1, 1].Value = "SupplierNo";
ws.Cells[1, 2].Value = "PartNo";
ws.Cells[1, 3].Value = "Comment";
ws.Cells[1, 4].Value = "EnterBy";
ws.Cells[1, 5].Value = "EnterDt";
ws.Cells[1, 6].Value = "CompleteDt";
ws.Cells["A:AZ"].AutoFitColumns();
return File(pck.GetAsByteArray(), "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", sFileName);
}
}
在我的剃须刀页面应用程序中,我有一个按钮,您可以单击该按钮创建一个 excel 文件,并且应该会自动将其保存到您的下载文件夹中。
下面的代码在本地主机上运行良好 - 我点击按钮,它保存到我的下载文件夹,我可以查看它。
但是,在我发布并尝试后,我收到一条错误消息,指出 "Could not find a part of the path 'C:\WINDOWS\system32\config\systemprofile\Downloads\PartCommentHistory.xlsx'."。
我也完全可以更改此代码,而不是拉出保存文件对话框 window 并允许用户首先选择文件的保存位置 - 但我不确定如何. Google 没有太大帮助,所以我们来了!
如果我实际导航到此路径,我会注意到没有 Downloads 文件夹。我尝试在我的代码中添加一个 if 语句,说明如果此处不存在 Downloads 文件夹,请先创建它,然后将文件保存在那里。但是,这会产生另一个错误,即我无权访问该路径。
public async Task<IActionResult> OnPostExportAsync(string currentFilter)
{
string sFilePath = Path.Combine(Environment.ExpandEnvironmentVariables("%USERPROFILE%"),"Downloads");
string sFileName = @"PartCommentHistory.xlsx";
string URL = string.Format("{0}://{1}/{2}", Request.Scheme, Request.Host, sFileName);
FileInfo file = new FileInfo(Path.Combine(sFilePath, sFileName));
var memory = new MemoryStream();
using (var fs = new FileStream(Path.Combine(sFilePath, sFileName), FileMode.Create, FileAccess.Write))
{
ExcelPackage pck = new ExcelPackage();
ExcelWorksheet ws = pck.Workbook.Worksheets.Add("Worksheet1");
List<CmtPartComment> commentlist = _context.CmtPartComments.Select(x => new CmtPartComment
{
SupplierNo = x.SupplierNo,
PartNo = x.PartNo,
Comment = x.Comment,
EnterBy = x.EnterBy,
EnteredDt = x.EnterDt.ToString("yyyy-MM-dd HH:mm:ss tt"),
CompletedDt = x.CompleteDt.ToString("yyyy-MM-dd HH:mm:ss tt")
}).Include(c => c.System).OrderByDescending(x => x.EnterDt).Where(x => x.PartNo == currentFilter).ToList();
ws.Cells[1, 1].Value = "SupplierNo";
ws.Cells[1, 2].Value = "PartNo";
ws.Cells[1, 3].Value = "Comment";
ws.Cells[1, 4].Value = "EnterBy";
ws.Cells[1, 5].Value = "EnterDt";
ws.Cells[1, 6].Value = "CompleteDt";
int recordIndex = 2;
foreach (var item in commentlist)
{
ws.Cells[recordIndex, 1].Value = item.SupplierNo;
ws.Cells[recordIndex, 2].Value = item.PartNo;
ws.Cells[recordIndex, 3].Value = item.Comment;
ws.Cells[recordIndex, 4].Value = item.EnterBy;
ws.Cells[recordIndex, 5].Value = item.EnteredDt;
ws.Cells[recordIndex, 6].Value = item.CompletedDt;
recordIndex++;
}
ws.Cells["A:AZ"].AutoFitColumns();
pck.SaveAs(fs);
}
using (var stream = new FileStream(Path.Combine(sFilePath, sFileName), FileMode.Open))
{
await stream.CopyToAsync(memory);
}
memory.Position = 0;
return File(memory, "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", sFileName);
}
您无法确定文件在客户端计算机上的保存位置。它似乎在您的机器上工作的唯一原因是因为您的机器充当服务器。您所能做的就是在用户下载文件时强制出现“保存”或“打开”对话框,这是通过将内容类型设置为 application/octet-stream
来实现的:
Do I need Content-Type: application/octet-stream for file download?
使用此方法获取文件夹路径
Environment.GetFolderPath(Environment.SpecialFolder.Yourspecialfoldernamehere, System.Environment.SpecialFolderOption.None)
例如
Environment.GetFolderPath(Environment.SpecialFolder.System));
在上面的例子中系统是一个特殊的文件夹。
对于您的问题,这是由于您通过 using (var fs = new FileStream(Path.Combine(sFilePath, sFileName), FileMode.Create, FileAccess.Write))
在服务器端创建了一个临时文件,该文件在服务器端可能不存在。
根据您的要求,您正在尝试创建一个文件并将其 return 发送到客户端。如果是这样,则无需在服务器端创建本地文件,您可以 return 文件的字节如下所示:
public async Task<IActionResult> OnPostExportByInMemoryAsync(string currentFilter)
{
string sFileName = @"PartCommentHistory.xlsx";
using (var pck = new ExcelPackage())
{
ExcelWorksheet ws = pck.Workbook.Worksheets.Add("Worksheet1");
ws.Cells[1, 1].Value = "SupplierNo";
ws.Cells[1, 2].Value = "PartNo";
ws.Cells[1, 3].Value = "Comment";
ws.Cells[1, 4].Value = "EnterBy";
ws.Cells[1, 5].Value = "EnterDt";
ws.Cells[1, 6].Value = "CompleteDt";
ws.Cells["A:AZ"].AutoFitColumns();
return File(pck.GetAsByteArray(), "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", sFileName);
}
}