.NET Core 6 Web API를 사용하여 단일 및 다중 파일 업로드

IFormFile 인터페이스 및 .NET에서 제공하는 다른 인터페이스를 사용하여 단일 및 다중 파일 업로드와 .NET Core 6 Web API를 사용한 단계별 구현에 대해 논의할 것입니다.

의제



소개
단계별 구현

전제 조건



.NET 코어 6 SDK
비주얼 스튜디오 2022
SQL 서버
우편 집배원

소개


  • .NET은 HTTP 요청에서 전송된 파일을 나타내는 IFormFile 인터페이스를 제공합니다.
  • 또한 ContentDisposition, ContentType, FileName, Headers, Name 및 Length와 같은 많은 속성을 제공합니다.
  • 또한 IFormFile은 요청 스트림 콘텐츠 복사, 읽기용 요청 스트림 열기 등과 같은 많은 메서드를 제공합니다.

  • 단계별 구현



    1 단계

    새 .NET Core 웹 API 만들기



    2 단계

    다음 NuGet 패키지 설치



    3단계

    다음 파일 엔티티 생성

    FileDetails.cs

    using System.ComponentModel.DataAnnotations;
    using System.ComponentModel.DataAnnotations.Schema;
    namespace FileUpload.Entities
    {
        [Table("FileDetails")]
        public class FileDetails
        {
            [Key]
            [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
            public int ID { get; set; }
            public string FileName { get; set; }
            public byte[] FileData { get; set; }
            public FileType FileType { get; set; }
        }
    }
    


    파일업로드모델

    namespace FileUpload.Entities
    {
        public class FileUploadModel
        {
            public IFormFile FileDetails { get; set; }
            public FileType FileType { get; set; }
        }
    }
    


    파일 유형

    namespace FileUpload.Entities
    {
        public enum FileType
        {
            PDF = 1,
            DOCX = 2
        }
    }
    


    4단계

    다음으로 Data 폴더 내의 DbContextClass.cs 클래스

    using FileUpload.Entities;
    using Microsoft.EntityFrameworkCore;
    namespace FileUpload.Data
    {
        public class DbContextClass : DbContext
        {
            protected readonly IConfiguration Configuration;
            public DbContextClass(IConfiguration configuration)
            {
                Configuration = configuration;
            }
            protected override void OnConfiguring(DbContextOptionsBuilder options)
            {
                options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection"));
            }
            public DbSet<FileDetails> FileDetails { get; set; }
        }
    }
    


    5단계

    IFileService 및 FileService 파일 만들기

    IFileService

    using FileUpload.Entities;
    namespace FileUpload.Services
    {
        public interface IFileService
        {
            public Task PostFileAsync(IFormFile fileData, FileType fileType);
            public Task PostMultiFileAsync(List<FileUploadModel> fileData);
            public Task DownloadFileById(int fileName);
        }
    }
    


    파일 서비스

    using FileUpload.Data;
    using FileUpload.Entities;
    using Microsoft.EntityFrameworkCore;
    namespace FileUpload.Services
    {
        public class FileService : IFileService
        {
            private readonly DbContextClass dbContextClass;
            public FileService(DbContextClass dbContextClass)
            {
                this.dbContextClass = dbContextClass;
            }
            public async Task PostFileAsync(IFormFile fileData, FileType fileType)
            {
                try
                {
                    var fileDetails = new FileDetails()
                    {
                        ID = 0,
                        FileName = fileData.FileName,
                        FileType = fileType,
                    };
                    using (var stream = new MemoryStream())
                    {
                        fileData.CopyTo(stream);
                        fileDetails.FileData = stream.ToArray();
                    }
                    var result = dbContextClass.FileDetails.Add(fileDetails);
                    await dbContextClass.SaveChangesAsync();
                }
                catch (Exception)
                {
                    throw;
                }
            }
            public async Task PostMultiFileAsync(List<FileUploadModel> fileData)
            {
                try
                {
                    foreach(FileUploadModel file in fileData)
                    {
                        var fileDetails = new FileDetails()
                        {
                            ID = 0,
                            FileName = file.FileDetails.FileName,
                            FileType = file.FileType,
                        };
                        using (var stream = new MemoryStream())
                        {
                            file.FileDetails.CopyTo(stream);
                            fileDetails.FileData = stream.ToArray();
                        }
                        var result = dbContextClass.FileDetails.Add(fileDetails);
                    }
                    await dbContextClass.SaveChangesAsync();
                }
                catch (Exception)
                {
                    throw;
                }
            }
            public async Task DownloadFileById(int Id)
            {
                try
                {
                    var file =  dbContextClass.FileDetails.Where(x => x.ID == Id).FirstOrDefaultAsync();
                    var content = new System.IO.MemoryStream(file.Result.FileData);
                    var path = Path.Combine(
                       Directory.GetCurrentDirectory(), "FileDownloaded",
                       file.Result.FileName);
                    await CopyStream(content, path);
                }
                catch (Exception)
                {
                    throw;
                }
            }
            public async Task CopyStream(Stream stream, string downloadPath)
            {
                using (var fileStream = new FileStream(downloadPath, FileMode.Create, FileAccess.Write))
                {
                   await stream.CopyToAsync(fileStream);
                }
            }
        }
    }
    


    6단계

    컨트롤러 섹션 내에 FilesController.cs 만들기

    using FileUpload.Entities;
    using FileUpload.Services;
    using Microsoft.AspNetCore.Http;
    using Microsoft.AspNetCore.Mvc;
    namespace FileUpload.Controllers
    {
        [Route("api/[controller]")]
        [ApiController]
        public class FilesController : ControllerBase
        {
            private readonly IFileService _uploadService;
            public FilesController(IFileService uploadService)
            {
                _uploadService = uploadService;
            }
            /// <summary>
            /// Single File Upload
            /// </summary>
            /// <param name="file"></param>
            /// <returns></returns>
            [HttpPost("PostSingleFile")]
            public async Task<ActionResult> PostSingleFile([FromForm] FileUploadModel fileDetails)
            {
                if(fileDetails == null)
                {
                    return BadRequest();
                }
                try
                {
                    await _uploadService.PostFileAsync(fileDetails.FileDetails, fileDetails.FileType);
                    return Ok();
                }
                catch (Exception)
                {
                    throw;
                }
            }
            /// <summary>
            /// Multiple File Upload
            /// </summary>
            /// <param name="file"></param>
            /// <returns></returns>
            [HttpPost("PostMultipleFile")]
            public async Task<ActionResult> PostMultipleFile([FromForm] List<FileUploadModel> fileDetails)
            {
                if (fileDetails == null)
                {
                    return BadRequest();
                }
                try
                {
                    await _uploadService.PostMultiFileAsync(fileDetails);
                    return Ok();
                }
                catch (Exception)
                {
                    throw;
                }
            }
            /// <summary>
            /// Download File
            /// </summary>
            /// <param name="file"></param>
            /// <returns></returns>
            [HttpGet("DownloadFile")]
            public async Task<ActionResult> DownloadFile(int id)
            {
                if (id < 1)
                {
                    return BadRequest();
                }
                try
                {
                    await _uploadService.DownloadFileById(id);
                    return Ok();
                }
                catch (Exception)
                {
                    throw;
                }
            }
        }
    }
    


    7단계

    프로그램 클래스 및 DI 컨테이너 내부에서 몇 가지 서비스 구성

    using FileUpload.Data;
    using FileUpload.Services;
    var builder = WebApplication.CreateBuilder(args);
    // Add services to the container.
    builder.Services.AddControllers();
    // Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
    builder.Services.AddEndpointsApiExplorer();
    builder.Services.AddSwaggerGen();
    builder.Services.AddDbContext<DbContextClass>();
    builder.Services.AddScoped<IFileService, FileService>();
    var app = builder.Build();
    // Configure the HTTP request pipeline.
    if (app.Environment.IsDevelopment())
    {
        app.UseSwagger();
        app.UseSwaggerUI();
    }
    app.UseAuthorization();
    app.MapControllers();
    app.Run();
    


    8단계

    SQL Server 내부에 새 데이터베이스를 만들고 이름을 FileUploadDemo로 지정합니다.

    9단계

    다음으로 다음 스크립트를 사용하여 FileDetails 테이블을 만듭니다.

    USE [FileUploadDemo]
    GO
    /****** Object:  Table [dbo].[FileDetails]    Script Date: 10/1/2022 5:51:22 PM ******/
    SET ANSI_NULLS ON
    GO
    SET QUOTED_IDENTIFIER ON
    GO
    CREATE TABLE [dbo].[FileDetails](
        [ID] [int] IDENTITY(1,1) NOT NULL,
        [FileName] [nvarchar](80) NOT NULL,
        [FileData] [varbinary](max) NOT NULL,
        [FileType] [int] NULL,
     CONSTRAINT [PK_FileDetails] PRIMARY KEY CLUSTERED
    (
        [ID] ASC
    )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON, OPTIMIZE_FOR_SEQUENTIAL_KEY = OFF) ON [PRIMARY]
    ) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]
    GO
    


    10단계

    appsettings.json 파일에 데이터베이스 연결을 넣습니다.

    {
      "Logging": {
        "LogLevel": {
          "Default": "Information",
          "Microsoft.AspNetCore": "Warning"
        }
      },
      "AllowedHosts": "*",
      "ConnectionStrings": {
        "DefaultConnection": "Data Source=DESKTOP-****;;Initial Catalog=FileUploadDemo;User Id=sa;Password=database;"
      }
    }
    


    11단계

    마지막으로 애플리케이션을 실행합니다.



    12단계

    이제 enum id를 기반으로 파일과 파일의 종류를 제공하여 swagger를 이용하여 하나의 파일을 업로드 하겠습니다.



    13단계

    또한 여러 파일을 업로드하기 위해 Postman을 사용합니다. 여기에서 배열 인덱스를 사용하여 파일과 유형을 전송하면 제대로 작동하는 것을 볼 수 있습니다.


    14단계

    나중에 파일 ID를 기반으로 지정된 경로 위치에서 로컬 시스템의 파일을 다운로드할 수 있습니다.


    15단계

    여기에서 지정된 위치에서 다운로드한 파일을 볼 수 있습니다.


    또한 데이터베이스에서 위의 끝점을 사용하여 이미 업로드한 모든 파일을 볼 수 있습니다.



    깃허브 URL:



    https://github.com/Jaydeep-007/FileUpload/tree/master/FileUpload

    결론



    이 기사에서는 IFormFile을 사용한 단일 및 다중 파일 업로드와 .NET Core Web API를 사용한 단계별 구현 및 데이터베이스에서 지정된 위치로 파일을 읽고 저장하는 방법에 대해 설명했습니다.

    행복한 학습!

    좋은 웹페이지 즐겨찾기