# 23.2、文件上传下载

## 文件下载

代码如下：

```csharp
[HttpGet]
[Route("~/api/sales/FileDownload")]
public IActionResult FileDownload(string path, string fileName)
{
    string filePath = Path.GetFullPath("~/temp/").Replace("~\\", "") + path;
    return new FileStreamResult(new FileStream(filePath, FileMode.Open), "application/octet-stream") { FileDownloadName = fileName };
}
```

## 文件上传

支持单文件、多文件上传，由于上传文件是耗时操作，所以尽量采用异步上传方式。代码如下：

```csharp
public async Task<IActionResult> UploadFileAsync(List<IFormFile> files)
{
    long size = files.Sum(f => f.Length);

    foreach (var formFile in files)
    {
        if (formFile.Length > 0)
        {
            var filePath = Path.GetTempFileName();  // 可以替代为你需要存储的真实路径

            using (var stream = System.IO.File.Create(filePath))
            {
                await formFile.CopyToAsync(stream);
            }
        }
    }

    return Ok(new { count = files.Count, size });
}
```

## 前端Angular下载示例

#### Get请求

只需要通过 `<a href='下载地址'>下载</a>` 即可。

#### Post请求

```javascript
// 导入HttpClient/HttpResponse 包
import { HttpClient, HttpResponse } from '@angular/common/http';

// 构造函数初始化
constructor(
    private httpClient: HttpClient
  ) { }

// 下载，第一个参数为post地址，第二个参数为post参数
this.httpClient.post('http://localhost:57310/api/Member/ExportMemberClaims', [{}], {
      responseType: 'blob',
      observe: 'events',
    }).subscribe((res: HttpResponse<Blob>) => {
      if (res.type !== 4) { return; }

      const objUrl = window.URL.createObjectURL(res.body);
      const a = document.createElement('a');
      a.href = objUrl;
      
      const fileName = 'excel.xlsx';  // 设置下载文件名
      a.download = decodeURIComponent(fileName);
      a.click();
      
      window.URL.revokeObjectURL(objUrl);
    });
```

## 文件上传下载推荐方式

通常我们将用户上传或提供下载的资源放在和源码同一服务器，这样用户下载和上传时会占用服务器内存资源，导致系统性能下降，所以我们通常将静态资源统一放在一台单独文件服务器中。由于自己托管文件服务器成本较高，所以推荐采用国内的 `七牛云` 或 `阿里云的 OSS 对象存储`。


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://monksoul.gitbook.io/hoa/qitagongneng/wenjianshangchuanxiazai.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
