Angular14+ASP.NET Core6 WebAPI上传文件展示与下载功能求助
ASP.NET Core 后端完善
1. 文件列表与下载接口
完善接口逻辑,增加异常处理、文件信息格式化,同时优化配置灵活性:
using Microsoft.AspNetCore.Mvc; using System.IO; [ApiController] [Route("api/files")] public class FilesController : ControllerBase { private readonly string _uploadPath; // 从配置文件读取上传路径,避免硬编码 public FilesController(IConfiguration configuration) { var uploadDir = configuration["FileSettings:UploadPath"] ?? "Uploads"; _uploadPath = Path.Combine(Directory.GetCurrentDirectory(), uploadDir); } [HttpGet("list")] public IActionResult GetFileList() { try { if (!Directory.Exists(_uploadPath)) { Directory.CreateDirectory(_uploadPath); return Ok(new List<FileInfoDto>()); } var files = new DirectoryInfo(_uploadPath) .GetFiles() .Select(f => new FileInfoDto { FileName = f.Name, FileSize = FormatFileSize(f.Length), CreatedTime = f.CreationTime.ToString("yyyy-MM-dd HH:mm:ss") }) .ToList(); return Ok(files); } catch (Exception ex) { return StatusCode(500, $"获取文件列表失败: {ex.Message}"); } } [HttpGet("download/{fileName}")] public IActionResult DownloadFile(string fileName) { try { // 处理文件名编码,避免特殊字符问题 var decodedFileName = Uri.UnescapeDataString(fileName); var filePath = Path.Combine(_uploadPath, decodedFileName); if (!System.IO.File.Exists(filePath)) { return NotFound("文件不存在"); } var contentType = GetContentType(decodedFileName); // 使用FileStream减少内存占用,支持大文件下载 var stream = new FileStream(filePath, FileMode.Open, FileAccess.Read); return File(stream, contentType, decodedFileName); } catch (Exception ex) { return StatusCode(500, $"下载文件失败: {ex.Message}"); } } // 格式化文件大小为易读格式 private string FormatFileSize(long bytes) { return bytes switch { < 1024 => $"{bytes} B", < 1048576 => $"{bytes / 1024:F2} KB", < 1073741824 => $"{bytes / 1048576:F2} MB", _ => $"{bytes / 1073741824:F2} GB" }; } // 获取文件MIME类型 private string GetContentType(string fileName) { var provider = new Microsoft.AspNetCore.StaticFiles.FileExtensionContentTypeProvider(); return provider.TryGetContentType(fileName, out var contentType) ? contentType : "application/octet-stream"; } } // 数据传输对象 public class FileInfoDto { public string FileName { get; set; } public string FileSize { get; set; } public string CreatedTime { get; set; } }
关键配置补充
- 在
appsettings.json添加文件路径配置:
{ "FileSettings": { "UploadPath": "Uploads" } }
- 配置CORS允许前端访问:
// Program.cs builder.Services.AddCors(options => { options.AddPolicy("AllowAngular", policy => policy.WithOrigins("http://localhost:4200") .AllowAnyHeader() .AllowAnyMethod()); }); app.UseCors("AllowAngular");
Angular 前端完善
1. 文件服务(file.service.ts)
封装HTTP请求,处理文件列表获取与下载逻辑:
import { Injectable } from '@angular/core'; import { HttpClient } from '@angular/common/http'; import { Observable } from 'rxjs'; export interface FileInfo { fileName: string; fileSize: string; createdTime: string; } @Injectable({ providedIn: 'root' }) export class FileService { private apiUrl = 'http://localhost:5000/api/files'; constructor(private http: HttpClient) { } getFileList(): Observable<FileInfo[]> { return this.http.get<FileInfo[]>(`${this.apiUrl}/list`); } downloadFile(fileName: string): Observable<Blob> { // 对文件名编码,避免特殊字符传递异常 const encodedFileName = encodeURIComponent(fileName); return this.http.get(`${this.apiUrl}/download/${encodedFileName}`, { responseType: 'blob' }); } }
2. 组件逻辑(file-list.component.ts)
实现文件列表加载与下载功能,添加状态提示:
import { Component, OnInit } from '@angular/core'; import { FileService, FileInfo } from '../services/file.service'; @Component({ selector: 'app-file-list', templateUrl: './file-list.component.html', styleUrls: ['./file-list.component.css'] }) export class FileListComponent implements OnInit { fileList: FileInfo[] = []; errorMessage = ''; isLoading = false; constructor(private fileService: FileService) { } ngOnInit(): void { this.loadFileList(); } loadFileList(): void { this.isLoading = true; this.fileService.getFileList().subscribe({ next: files => { this.fileList = files; this.errorMessage = ''; this.isLoading = false; }, error: err => { this.errorMessage = err.error || '加载文件列表失败'; this.isLoading = false; } }); } downloadFile(fileName: string): void { this.fileService.downloadFile(fileName).subscribe({ next: blob => { const url = window.URL.createObjectURL(blob); const a = document.createElement('a'); a.href = url; a.download = fileName; document.body.appendChild(a); a.click(); // 清理资源 window.URL.revokeObjectURL(url); document.body.removeChild(a); }, error: err => { this.errorMessage = err.error || '下载文件失败'; } }); } }
3. 页面模板(file-list.component.html)
展示文件列表,添加加载状态与错误提示:
<div class="container mt-4"> <h2>服务器文件列表</h2> <!-- 加载状态 --> <div *ngIf="isLoading" class="text-center"> <div class="spinner-border" role="status"> <span class="visually-hidden">加载中...</span> </div> </div> <!-- 错误提示 --> <div *ngIf="errorMessage && !isLoading" class="alert alert-danger mt-3">{{ errorMessage }}</div> <!-- 文件列表表格 --> <table *ngIf="!isLoading" class="table table-striped mt-3"> <thead> <tr> <th>文件名</th> <th>文件大小</th> <th>创建时间</th> <th>操作</th> </tr> </thead> <tbody> <tr *ngFor="let file of fileList"> <td>{{ file.fileName }}</td> <td>{{ file.fileSize }}</td> <td>{{ file.createdTime }}</td> <td> <button class="btn btn-primary" (click)="downloadFile(file.fileName)">下载</button> </td> </tr> <tr *ngIf="fileList.length === 0 && !errorMessage"> <td colspan="4" class="text-center text-muted">暂无文件</td> </tr> </tbody> </table> </div>
必要配置
确保AppModule中导入HttpClientModule:
import { HttpClientModule } from '@angular/common/http'; @NgModule({ imports: [HttpClientModule], }) export class AppModule { }
额外优化建议
- 添加文件删除功能:后端实现删除接口,前端增加删除按钮并确认提示
- 支持文件搜索、排序:前端添加搜索框,对文件名进行过滤,或按创建时间/大小排序
- 限制文件访问权限:后端添加身份验证,仅允许授权用户查看和下载文件
- 大文件下载优化:后端支持断点续传,前端显示下载进度
内容的提问来源于stack exchange,提问作者salah afourer
相关产品推荐
相关产品推荐

