 闽公网安备 35020302035485号
                
                闽公网安备 35020302035485号
                • 网络不稳定:在网络中断的情况下,用户需要重新上传整个文件。
	
• 流式上传:通过流式处理避免将整个文件加载到内存中。
	
public void ConfigureServices(IServiceCollection services)
{
    services.Configure<IISServerOptions>(options =>
    {
        options.MaxRequestBodySize = int.MaxValue; // 设置最大请求大小
    });
}
流式上传[HttpPost("upload")]
public async Task<IActionResult> UploadLargeFile(IFormFile file)
{
    if (file == null || file.Length == 0)
        return BadRequest("未选择文件");
   // 堆代码 duidaima.com
    var filePath = Path.Combine(Directory.GetCurrentDirectory(), "uploads", file.FileName);
    using (var stream = new FileStream(filePath, FileMode.Create))
    {
        await file.CopyToAsync(stream); // 使用流式处理
    }
    return Ok("文件上传成功");
}
二、分块上传• 后端合并:接收所有小块后,按顺序合并为完整文件。
	
function uploadFile(file) {
    const chunkSize = 1 * 1024 * 1024; // 每块1MB
    let start = 0;
    let end = chunkSize;
    functionuploadChunk() {
        if (start >= file.size) return;
        const chunk = file.slice(start, end);
        const formData = newFormData();
        formData.append('chunk', chunk);
        formData.append('fileName', file.name);
        fetch('/api/upload/chunk', {
            method: 'POST',
            body: formData
        }).then(() => {
            start = end;
            end += chunkSize;
            uploadChunk(); // 递归上传下一小块
        });
    }
    uploadChunk();
}
后端合并private staticreadonly Dictionary<string, List<byte[]>> chunks = new();
[HttpPost("chunk")]
public IActionResult UploadChunk([FromForm] byte[] chunk, [FromForm] string fileName)
{
    if (!chunks.ContainsKey(fileName))
        chunks[fileName] = new List<byte[]>();
    chunks[fileName].Add(chunk);
    return Ok("分块上传成功");
}
[HttpPost("merge")]
public IActionResult MergeChunks([FromForm] string fileName)
{
    if (!chunks.ContainsKey(fileName))
        return NotFound("分块不存在");
    var allBytes = chunks[fileName].SelectMany(c => c).ToArray();
    var filePath = Path.Combine(Directory.GetCurrentDirectory(), "uploads", fileName);
    System.IO.File.WriteAllBytes(filePath, allBytes);
    chunks.Remove(fileName);
    return Ok("文件合并成功");
}
三、断点续传public class UploadProgress
{
    public string FileName { get; set; }
    public int TotalChunks { get; set; }
    public List<bool> UploadedChunks { get; set; } = new();
}
恢复上传逻辑[HttpGet("progress/{fileName}")]
public IActionResult GetUploadProgress(string fileName)
{
    // 查询数据库或文件系统获取上传进度
    var progress = GetProgressFromDatabase(fileName);
    return Ok(progress);
}
四、高效的文件下载[HttpGet("download/{fileName}")]
public IActionResult DownloadFile(string fileName)
{
    var filePath = Path.Combine(Directory.GetCurrentDirectory(), "uploads", fileName);
    if (!System.IO.File.Exists(filePath))
        return NotFound("文件不存在");
    var stream = new FileStream(filePath, FileMode.Open, FileAccess.Read);
    return File(stream, "application/octet-stream", fileName);
}
支持断点续传[HttpGet("resume-download/{fileName}")]
public IActionResult ResumeDownload(string fileName)
{
    var filePath = Path.Combine(Directory.GetCurrentDirectory(), "uploads", fileName);
    if (!System.IO.File.Exists(filePath))
        return NotFound("文件不存在");
    var fileSize = new FileInfo(filePath).Length;
    var rangeHeader = Request.Headers["Range"].ToString();
    if (!string.IsNullOrEmpty(rangeHeader))
    {
        var rangeValues = RangeHeaderValue.Parse(rangeHeader).Ranges.First();
        var start = rangeValues.From ?? 0;
        var length = rangeValues.To - start + 1;
        var stream = new FileStream(filePath, FileMode.Open, FileAccess.Read);
        stream.Seek(start, SeekOrigin.Begin);
        Response.Headers["Content-Range"] = $"bytes {start}-{rangeValues.To}/{fileSize}";
        Response.StatusCode = StatusCodes.Status206PartialContent;
        return File(stream, "application/octet-stream", fileName, false, (int)length);
    }
    return File(new FileStream(filePath, FileMode.Open, FileAccess.Read), "application/octet-stream", fileName);
}
总结