Web API を使用した複数ファイルのアップロードとダウンロード

Web API を使用した複数ファイルのアップロードとダウンロード

ASP.NET Core 6.0 Web API を使用して複数のファイルをアップロードおよびダウンロードする簡単な手順を紹介します。

最終更新 2022/07/23 9:37
Jay Krishna Reddy
読了目安 4 分
カテゴリ
ASP.NET Core
タグ
.NET C# ASP.NET Core Web API

原文著者:Jay Krishna Reddy

原文リンク:https://www.c-sharpcorner.com/article/upload-and-download-multiple-files-using-web-api/

翻訳:砂漠の果ての狼(Google翻訳による補助。記事内のバージョンは.NET 6にアップグレード)

--- 本文開始 ---

本日は、ASP.NET Core 6.0 Web API を使用した複数ファイルのアップロードとダウンロードの簡単なプロセスを紹介します。

手順

まずVisual Studioで空のWeb APIプロジェクトを作成し、ターゲットフレームワークとして .NET 6.0 を選択します。

このプロジェクトでは外部パッケージは使用しません。

Services フォルダを作成し、その中に FileService クラスと IFileService インターフェースを作成します。

この FileService.cs では次の3つのメソッドを使用しています。

  • UploadFile
  • DownloadFile
  • SizeConverter

アップロードファイルを保存するフォルダが必要なため、フォルダ名を文字列で渡すパラメータを追加し、アップロードされたすべてのファイルをそのフォルダに保存します。

FileService.cs

using System.IO.Compression;

namespace FileUploadAndDownload.Services;

public class FileService : IFileService
{
    #region Property

    private readonly IWebHostEnvironment _webHostEnvironment;

    #endregion

    #region Constructor

    public FileService(IWebHostEnvironment webHostEnvironment)
    {
        _webHostEnvironment = webHostEnvironment;
    }

    #endregion

    #region Upload File

    public void UploadFile(List<IFormFile> files, string subDirectory)
    {
        subDirectory = subDirectory ?? string.Empty;
        var target = Path.Combine(_webHostEnvironment.ContentRootPath, subDirectory);

        Directory.CreateDirectory(target);

        files.ForEach(async file =>
        {
            if (file.Length <= 0) return;
            var filePath = Path.Combine(target, file.FileName);
            await using var stream = new FileStream(filePath, FileMode.Create);
            await file.CopyToAsync(stream);
        });
    }

    #endregion

    #region Download File

    public (string fileType, byte[] archiveData, string archiveName) DownloadFiles(string subDirectory)
    {
        var zipName = $"archive-{DateTime.Now:yyyy_MM_dd-HH_mm_ss}.zip";

        var files = Directory.GetFiles(Path.Combine(_webHostEnvironment.ContentRootPath, subDirectory)).ToList();

        using var memoryStream = new MemoryStream();
        using (var archive = new ZipArchive(memoryStream, ZipArchiveMode.Create, true))
        {
            files.ForEach(file =>
            {
                var theFile = archive.CreateEntry(Path.GetFileName(file));
                using var binaryWriter = new BinaryWriter(theFile.Open());
                binaryWriter.Write(File.ReadAllBytes(file));
            });
        }

        return ("application/zip", memoryStream.ToArray(), zipName);
    }

    #endregion

    #region Size Converter

    public string SizeConverter(long bytes)
    {
        var fileSize = new decimal(bytes);
        var kilobyte = new decimal(1024);
        var megabyte = new decimal(1024 * 1024);
        var gigabyte = new decimal(1024 * 1024 * 1024);

        return fileSize switch
        {
            _ when fileSize < kilobyte => "Less then 1KB",
            _ when fileSize < megabyte =>
                $"{Math.Round(fileSize / kilobyte, 0, MidpointRounding.AwayFromZero):##,###.##}KB",
            _ when fileSize < gigabyte =>
                $"{Math.Round(fileSize / megabyte, 2, MidpointRounding.AwayFromZero):##,###.##}MB",
            _ when fileSize >= gigabyte =>
                $"{Math.Round(fileSize / gigabyte, 2, MidpointRounding.AwayFromZero):##,###.##}GB",
            _ => "n/a"
        };
    }

    #endregion
}

SizeConverter 関数は、サーバーにアップロードされたファイルの実際のサイズを取得するために使用します。

IFileService.cs

namespace FileUploadAndDownload.Services;

public interface IFileService
{
    void UploadFile(List<IFormFile> files, string subDirectory);
    (string fileType, byte[] archiveData, string archiveName) DownloadFiles(string subDirectory);
    string SizeConverter(long bytes);
}

次に、このサービス依存関係を Program.cs ファイルに追加します。

Program.cs

using FileUploadAndDownload.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.AddTransient<IFileService, FileService>();

var app = builder.Build();

// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
    app.UseSwagger();
    app.UseSwaggerUI();
}

app.UseHttpsRedirection();

app.UseAuthorization();

app.MapControllers();

app.Run();

FileController を作成し、そのコンストラクターで IFileService を注入します。

FileController.cs

using FileUploadAndDownload.Services;
using Microsoft.AspNetCore.Mvc;
using System.ComponentModel.DataAnnotations;

namespace FileUploadAndDownload.Controllers;

[Route("api/[controller]")]
[ApiController]
public class FileController : ControllerBase
{
    private readonly IFileService _fileService;

    public FileController(IFileService fileService)
    {
        _fileService = fileService;
    }

    [HttpPost(nameof(Upload))]
    public IActionResult Upload([Required] List<IFormFile> formFiles, [Required] string subDirectory)
    {
        try
        {
            _fileService.UploadFile(formFiles, subDirectory);

            return Ok(new { formFiles.Count, Size = _fileService.SizeConverter(formFiles.Sum(f => f.Length)) });
        }
        catch (Exception ex)
        {
            return BadRequest(ex.Message);
        }
    }

    [HttpGet(nameof(Download))]
    public IActionResult Download([Required] string subDirectory)
    {
        try
        {
            var (fileType, archiveData, archiveName) = _fileService.DownloadFiles(subDirectory);

            return File(archiveData, fileType, archiveName);
        }
        catch (Exception ex)
        {
            return BadRequest(ex.Message);
        }
    }
}

APIは swaggerpostman でテストできます。

ここではアップロードとダウンロード用に作成した2つのAPIが表示されていますので、それぞれを個別にテストしてみましょう。

subDirectory フィールドにファイル保存先のフォルダ名を入力し、下にファイルを追加して、対応するサブフォルダ名でサーバーに保存します。応答として、ファイルの総数とアップロードされたすべてのファイルの合計実サイズが表示されます。

次にダウンロードAPIを確認します。フォルダ内に複数のファイルがあるため、Zip ファイルとしてダウンロードされ、解凍してファイルを確認する必要があります。

まとめ

Web API インターフェースを使用したファイルのアップロードとダウンロードは、Blazor Server、Blazor Client、MAUI、Winform、WPF などのクライアントプログラムに適用できます。後日、これらのインターフェースを呼び出すクライアント側の実装を紹介する予定です。

.... 学習を続けてください !!!

さらに探索

関連読書

その他の記事
同じカテゴリ / 同じタグ 2022/06/22

ASP.NET Core WebAPI でローカリゼーションを実装する(単一リソースファイル)

Microsoft のデフォルトは、1 つのクラスに複数のリソースファイルを対応させる方法であり、使用がやや面倒です。本記事では、単一リソースファイルの使用方法を紹介します。つまり、プロジェクト全体のすべてのクラスが 1 セットの多言語リソースファイルに対応します。

続きを読む
同じカテゴリ / 同じタグ 2022/04/13

ASP.NET Core WebApiの戻り結果統一包装の実践

WebApiの結果を統一して返す際に、より良い制限方法や、よりシンプルで強力な結果のラッピングについて考えるようになりました。絶えず考えを巡らせ改善する中で、ようやく初歩的な成果を得たので共有します。学びに終わりはなく、考えにも終わりはありません。皆様と共に励みたいと思います。

続きを読む