翻阅了微软的文档,实质上就是把文件拆分成很多个缓冲区,并返回读取到的数据。还是值得分享学习,如果有更好的办法,可以留言。
下面的示例演示如何在服务器端应用中上传文件,同时向用户显示上传进度。
若要在测试应用中使用以下示例:
- 创建文件夹来保存已上传用于
Development
环境的文件:Development/unsafe_uploads
。 - 配置最大文件夹大小(
maxFileSize
在下例中是 15 KB)和允许的文件最大数量(maxAllowedFiles
在下例中是 3)。 - 如果需要,请将缓冲区设置为其他值(在下例中是 10 KB),以提高进度报告中的粒度。 由于性能和安全方面的问题,建议不要使用大于 30 KB 的缓冲区。
- 注意后端需要对数据进行检验打开文件时,需要重新读取文件流,不可以使用文件字节数组,否则会导致文件失效。不过这样会导致对同意文件读取2次有点重复,有没有小伙伴可以优化解答一下办法么
@page "/file-upload-3"
@using System
@using System.IO
@using Microsoft.AspNetCore.Hosting
@using Microsoft.Extensions.Logging
@inject ILogger<FileUpload3> Logger
@inject IWebHostEnvironment Environment
<h3>Upload Files</h3>
<p>
<label>
Max file size:
<input type="number" @bind="maxFileSize" />
</label>
</p>
<p>
<label>
Max allowed files:
<input type="number" @bind="maxAllowedFiles" />
</label>
</p>
<p>
<label>
Upload up to @maxAllowedFiles of up to @maxFileSize bytes:
<InputFile OnChange="@LoadFiles" multiple />
</label>
</p>
@if (isLoading)
{
<p>Progress: @string.Format("{0:P0}", progressPercent)</p>
}
else
{
<ul>
@foreach (var file in loadedFiles)
{
<li>
<ul>
<li>Name: @file.Name</li>
<li>Last modified: @file.LastModified.ToString()</li>
<li>Size (bytes): @file.Size</li>
<li>Content type: @file.ContentType</li>
</ul>
</li>
}
</ul>
}
@code {
private List<IBrowserFile> loadedFiles = new();
private long maxFileSize = 1024 * 15;
private int maxAllowedFiles = 3;
private bool isLoading;
private decimal progressPercent;
private async Task LoadFiles(InputFileChangeEventArgs e)
{
isLoading = true;
loadedFiles.Clear();
progressPercent = 0;
foreach (var file in e.GetMultipleFiles(maxAllowedFiles))
{
try
{
//随机名称
var trustedFileName = Path.GetRandomFileName();
//存储路径(可以用自己的的配置文件写入路径)
var path = Path.Combine(Environment.ContentRootPath,
Environment.EnvironmentName, "unsafe_uploads", trustedFileName);
await using FileStream writeStream = new(path, FileMode.Create);
using var readStream = file.OpenReadStream(maxFileSize);
var bytesRead = 0;
var totalRead = 0;
var buffer = new byte[1024 * 10];
while ((bytesRead = await readStream.ReadAsync(buffer)) != 0)
{
//每次读取返回的大小
totalRead += bytesRead;
await writeStream.WriteAsync(buffer, 0, bytesRead);
//每次读取返回的大小/文件总大小
progressPercent = Decimal.Divide(totalRead, file.Size);
StateHasChanged();
}
loadedFiles.Add(file);
}
catch (Exception ex)
{
Logger.LogError("File: {Filename} Error: {Error}",
file.Name, ex.Message);
}
}
isLoading = false;
}
}