zl程序教程

您现在的位置是:首页 >  后端

当前栏目

ASP.NET Core – Upload and Download Files (上传和下载文件)

2023-09-27 14:23:55 时间

前言

以前得文章 Asp.net core 学习笔记 ( upload/download files 文件上传与下载 ), 这篇是修订版.

 

Handle Upload File (处理上传文件)

我的例子是基于 Web API 和 Ajax 的.

前端 Ajax

const btn = document.querySelector('button')!;
btn.addEventListener('click', async () => {
  const formData = new FormData();
  formData.append('file', createTextBlob('Hello World'), 'text1.txt');
  // formData.append('file', createTextBlob('Derrick'), 'text2.txt'); // for multiple file

  await fetch('http://localhost:5221/Upload', {
    method: 'POST',
    body: formData,
  });

  function createTextBlob(text: string): Blob {
    const textEncoder = new TextEncoder();
    const bytes = textEncoder.encode(text);
    return new Blob([bytes], {
      type: 'text/plain',
    });
  }
});

upload 一个/多个 text file.

Web API

DTO

public class UploadDto
{
    public IFormFile File { get; set; } = null!;
}

关键就是这个 IFormFile, 它就是用来接收前端 File 的.

Controller

[ApiController]
public class UploadController : ControllerBase
{
    [HttpPost("Upload")]
    [Consumes("multipart/form-data")]
    [ProducesResponseType(StatusCodes.Status200OK)]
    public async Task<ActionResult> Upload([FromForm] UploadDto dto)
    {
        return Ok("ok");
    }
}

把 upload file 写入 disk

var fileRootFullPath = Path.Combine(AppContext.BaseDirectory, $@"..\..\..\{dto.File.FileName}");
using var fileStream = System.IO.File.Create(fileRootFullPath);
await dto.File.CopyToAsync(fileStream);

IFormFile 用法很简单, 它通过 .FileName 拿到文件名, 通过 CopyToAsync 把 stream 传给别人. 比如上面是把 stream 导入 file stream, 这样就写入磁盘了.

把 upload file stream 传给任何人使用

// 直接读 string 出来
using var stream = dto.File.OpenReadStream();
using var streamReader = new StreamReader(stream, encoding: Encoding.UTF8);
var text = await streamReader.ReadToEndAsync(); // Hello World

通过 OpenReadStream() 导出 stream 就可以做任何 stream 处理了.

handle multiple files

// JavaScript
const formData = new FormData();
formData.append('file', createTextBlob('Hello World'), 'text1.txt');
formData.append('file', createTextBlob('Derrick'), 'text2.txt'); // for multiple file

// C#
public class UploadDto
{
    public List<IFormFile> File { get; set; } = null!;
}

没什么提别的, 就只是换成了 List<IFormFile>

 

Download File (下载文件)

前端 HTML

<a href="http://localhost:5221/Download" download="">download</a>

Web API Controller

[ApiController]
public class UploadController : ControllerBase
{
    [HttpGet("Download")]
    [Produces(MediaTypeNames.Text.Plain)]
    [ProducesResponseType(StatusCodes.Status200OK)]
    public ActionResult Download()
    {
        return new FileContentResult(Encoding.UTF8.GetBytes("Hello World"), "text/plain")
        {
            FileDownloadName = "text.txt"
        };

        // 下面这个写法和上面是等价的
        // return File(
        //     fileContents: Encoding.UTF8.GetBytes("Hello World"),
        //     contentType: "text/plain",
        //     fileDownloadName: "text.txt"
        // );
    }
}

返回 bytes, 声明 ContentType 和 Download File Name 就可以了. 简单