Ben*_*ual 25 c# asp.net-core blazor
我HttpGet在我的 Server-API 中创建了一个 CSV 文件并返回它FileStreamResult:
[HttpGet]
public IActionResult Get() {
// do logic to create csv in memoryStream
return new FileStreamResult(memoryStream, "text/csv;charset=utf-8") {
FileDownloadName = "products.csv",
};
}
Run Code Online (Sandbox Code Playgroud)
在我的 Blazor-Client 应用程序中,我创建了一个带有处理程序的按钮:
private async Task DownloadCatalog() {
var file = HttpClient.GetAsync("api/csvProduct");
// ... how do I download the file in the browser?
}
Run Code Online (Sandbox Code Playgroud)
调用了控制器中的 Get,但我不知道该怎么做才能在 api 调用后将文件下载到浏览器中。
Pan*_*vos 45
浏览器不允许脚本写入文件系统,无论是用 JavaScript 还是 WebAssembly 编写。仅当用户单击链接时,浏览器才会显示下载对话框。
使用链接按钮
如果最终文件直接从服务器返回,最简单的解决方案是使用带有 API 端点 URL 的链接按钮(可能在运行时计算)。您可以使用该download属性来指定文件名。当用户单击链接时,将检索文件并使用download名称保存
例如 :
<a id="exportCsv" class="btn" href="api/csvProduct" download="MyFile.csv"
role="button" target="=_top">Export to CSV</a>
Run Code Online (Sandbox Code Playgroud)
或者
@if (_exportUrl != null)
{
<a id="exportCsv" class="btn" href="@_exportUrl" download="MyFile.csv"
role="button" target="=_top">Export to Csv</a>
}
...
int _productId=0;
string? _exportUrl=null;
async Task Search()
{
//Get and display a product summary
_model=await GetProductSummary(_productId);
//Activate the download URL
_exportUrl = $"api/csvProduct/{_productId}";
}
Run Code Online (Sandbox Code Playgroud)
使用动态生成的数据链接
如果这不可能,您必须在 JavaScript 中使用数据 URL 或 Blob 创建一个链接元素,然后单击它。速度太慢有以下三个原因:
在 Blazor WebAssembly 应用程序中生成并高效导出文件一文展示了如何使用某些 Blazor 运行时技巧传递字节而不进行封送。
如果您使用 Blazor WASM,则可以使用 useInvokeUnmarshalled传递byte[]数组并使其Uint8Array在 JavaScript 中显示为 a。
byte[] file = Enumerable.Range(0, 100).Cast<byte>().ToArray();
string fileName = "file.bin";
string contentType = "application/octet-stream";
// Check if the IJSRuntime is the WebAssembly implementation of the JSRuntime
if (JSRuntime is IJSUnmarshalledRuntime webAssemblyJSRuntime)
{
webAssemblyJSRuntime.InvokeUnmarshalled<string, string, byte[], bool>("BlazorDownloadFileFast", fileName, contentType, file);
}
else
{
// Fall back to the slow method if not in WebAssembly
await JSRuntime.InvokeVoidAsync("BlazorDownloadFile", fileName, contentType, file);
}
Run Code Online (Sandbox Code Playgroud)
JavaScriptBlazorDownloadFileFast方法检索数组,将其转换为文件,然后转换URL.createObjectURL为可单击的安全数据 URL:
function BlazorDownloadFileFast(name, contentType, content) {
// Convert the parameters to actual JS types
const nameStr = BINDING.conv_string(name);
const contentTypeStr = BINDING.conv_string(contentType);
const contentArray = Blazor.platform.toUint8Array(content);
// Create the URL
const file = new File([contentArray], nameStr, { type: contentTypeStr });
const exportUrl = URL.createObjectURL(file);
// Create the <a> element and click on it
const a = document.createElement("a");
document.body.appendChild(a);
a.href = exportUrl;
a.download = nameStr;
a.target = "_self";
a.click();
// We don't need to keep the url, let's release the memory
// On Safari it seems you need to comment this line... (please let me know if you know why)
URL.revokeObjectURL(exportUrl);
a.remove();
}
Run Code Online (Sandbox Code Playgroud)
对于 Blazor Server,封送是不可避免的。BlazorDownloadFile在这种情况下,将调用较慢的方法。该byte[]数组被编组为 BASE64 字符串,必须对其进行解码。不幸的是,JavaScriptatob和btoa函数无法处理每个值,因此我们需要另一种方法将 Base64 解码为 Uint8Array:
function BlazorDownloadFile(filename, contentType, content) {
// Blazor marshall byte[] to a base64 string, so we first need to convert the string (content) to a Uint8Array to create the File
const data = base64DecToArr(content);
// Create the URL
const file = new File([data], filename, { type: contentType });
const exportUrl = URL.createObjectURL(file);
// Create the <a> element and click on it
const a = document.createElement("a");
document.body.appendChild(a);
a.href = exportUrl;
a.download = filename;
a.target = "_self";
a.click();
// We don't need to keep the url, let's release the memory
// On Safari it seems you need to comment this line... (please let me know if you know why)
URL.revokeObjectURL(exportUrl);
a.remove();
}
Run Code Online (Sandbox Code Playgroud)
以及解码器函数,借用自Mozilla的Base64文档
// Convert a base64 string to a Uint8Array. This is needed to create a blob object from the base64 string.
// The code comes from: https://developer.mozilla.org/fr/docs/Web/API/WindowBase64/D%C3%A9coder_encoder_en_base64
function b64ToUint6(nChr) {
return nChr > 64 && nChr < 91 ? nChr - 65 : nChr > 96 && nChr < 123 ? nChr - 71 : nChr > 47 && nChr < 58 ? nChr + 4 : nChr === 43 ? 62 : nChr === 47 ? 63 : 0;
}
function base64DecToArr(sBase64, nBlocksSize) {
var
sB64Enc = sBase64.replace(/[^A-Za-z0-9\+\/]/g, ""),
nInLen = sB64Enc.length,
nOutLen = nBlocksSize ? Math.ceil((nInLen * 3 + 1 >> 2) / nBlocksSize) * nBlocksSize : nInLen * 3 + 1 >> 2,
taBytes = new Uint8Array(nOutLen);
for (var nMod3, nMod4, nUint24 = 0, nOutIdx = 0, nInIdx = 0; nInIdx < nInLen; nInIdx++) {
nMod4 = nInIdx & 3;
nUint24 |= b64ToUint6(sB64Enc.charCodeAt(nInIdx)) << 18 - 6 * nMod4;
if (nMod4 === 3 || nInLen - nInIdx === 1) {
for (nMod3 = 0; nMod3 < 3 && nOutIdx < nOutLen; nMod3++, nOutIdx++) {
taBytes[nOutIdx] = nUint24 >>> (16 >>> nMod3 & 24) & 255;
}
nUint24 = 0;
}
}
return taBytes;
}
Run Code Online (Sandbox Code Playgroud)
开拓者6
最近发布的ASP.NET Core 6 Preview 6不再封送byte[]为 Base64 字符串。应该可以使用下面的函数
function BlazorDownloadFile(filename, contentType, data) {
// Create the URL
const file = new File([data], filename, { type: contentType });
const exportUrl = URL.createObjectURL(file);
// Create the <a> element and click on it
const a = document.createElement("a");
document.body.appendChild(a);
a.href = exportUrl;
a.download = filename;
a.target = "_self";
a.click();
// We don't need to keep the url, let's release the memory
// On Safari it seems you need to comment this line... (please let me know if you know why)
URL.revokeObjectURL(exportUrl);
a.remove();
}
Run Code Online (Sandbox Code Playgroud)
小智 12
为了下载文件,您必须使用 Microsoft JSInterop。有很多方法可以实现您的请求。我使用的一种方法是将文件作为字节数组获取,然后将其转换为 base64string。最后调用您在 javascript 中创建的函数。
在服务器端
js.InvokeVoidAsync("jsSaveAsFile",
filename,
Convert.ToBase64String(GetFileByteArrayFunction())
);
Run Code Online (Sandbox Code Playgroud)
在 wwwroot 的 javascript 文件中创建一个函数
function jsSaveAsFile(filename, byteBase64) {
var link = document.createElement('a');
link.download = filename;
link.href = "data:application/octet-stream;base64," + byteBase64;
document.body.appendChild(link);
link.click();
document.body.removeChild(link);}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
49532 次 |
| 最近记录: |