Azure Blob Storageにファイルをアップロードし、FastAPIで後続処理を行うReactアプリの実装

## 概要

この記事では、Azure Blob Storageにファイルをアップロードし、その後FastAPIを使用して後続処理を行うReactアプリの実装方法を紹介します。また、不特定多数のユーザーがアクセスすることを想定し、ファイル名の重複を防ぐ方法とセキュリティについても説明します。

## 使用技術

- フロントエンド: React + TypeScript
- バックエンド: Python + FastAPI
- クラウドストレージ: Azure Blob Storage

## フロントエンド実装 (React + TypeScript)

まず、Azure Blob Storageにファイルをアップロードするための準備として、`@azure/storage-blob`パッケージをインストールします。

```bash
npm install @azure/storage-blob
```

次に、ユーザーが選択したファイルをAzure Blob StorageにアップロードするReactコンポーネントを作成します。

### ファイル名の衝突を防ぐためにUUIDを使用

不特定多数のユーザーがアップロードを行う場合、ファイル名が重複するリスクがあります。これを回避するために、UUIDを使用してユニークなファイル名を生成します。`uuid`パッケージをインストールして利用します。

```bash
npm install uuid
```

```typescript
import React, { useState } from 'react';
import { BlobServiceClient } from '@azure/storage-blob';
import { v4 as uuidv4 } from 'uuid';

const UploadComponent: React.FC = () => {
    const [file, setFile] = useState<File | null>(null);
    const [uploadStatus, setUploadStatus] = useState<string>('');

    const handleFileChange = (e: React.ChangeEvent<HTMLInputElement>) => {
        if (e.target.files) {
            setFile(e.target.files[0]);
        }
    };

    const uploadFile = async () => {
        if (!file) {
            alert("Please select a file first!");
            return;
        }

        try {
            // SASトークンとBlob StorageのURL
            const sasToken = "YOUR_SAS_TOKEN";
            const blobServiceClient = new BlobServiceClient(`https://YOUR_STORAGE_ACCOUNT.blob.core.windows.net/?${sasToken}`);
            const containerClient = blobServiceClient.getContainerClient("YOUR_CONTAINER_NAME");

            // UUIDを用いてユニークなファイル名を生成
            const uniqueFileName = `${uuidv4()}-${file.name}`;
            const blockBlobClient = containerClient.getBlockBlobClient(uniqueFileName);
            const uploadBlobResponse = await blockBlobClient.uploadBrowserData(file);
            console.log(`Upload block blob ${uniqueFileName} successfully`, uploadBlobResponse.requestId);

            setUploadStatus('File uploaded successfully!');

            // ファイルがアップロードされた後にWebAPIにリクエスト
            const response = await fetch('http://localhost:8000/process', {
                method: 'POST',
                headers: {
                    'Content-Type': 'application/json',
                },
                body: JSON.stringify({ fileName: uniqueFileName }),
            });

            const result = await response.json();
            console.log(result);
        } catch (err) {
            console.error("Error uploading file:", err);
            setUploadStatus('File upload failed!');
        }
    };

    return (
        <div>
            <input type="file" onChange={handleFileChange} />
            <button onClick={uploadFile}>Upload</button>
            <p>{uploadStatus}</p>
        </div>
    );
};

export default UploadComponent;
```

## バックエンド実装 (Python + FastAPI)

FastAPIを使用して、フロントエンドから受け取ったファイル名を基に後続処理を行います。

まず、FastAPIをインストールします。

```bash
pip install fastapi uvicorn
```

次に、FastAPIアプリケーションを実装します。

```python
from fastapi import FastAPI, HTTPException
from pydantic import BaseModel

app = FastAPI()

class FileProcessRequest(BaseModel):
    fileName: str

@app.post("/process")
async def process_file(request: FileProcessRequest):
    file_name = request.fileName
    # ここに後続処理を記述
    print(f"Processing file: {file_name}")

    # 処理結果を返す
    return {"message": f"File {file_name} processed successfully"}
```

サーバーを起動するには、以下のコマンドを実行します。

```bash
uvicorn main:app --reload
```

## まとめ

- **ファイル名のユニーク性**: UUIDを用いてファイル名を生成することで、ファイル名の重複を防ぎます。
- **セキュリティ**: Azure AD認証を使用してアクセス制御を行い、セキュアなファイルアップロードを実現します。

これにより、不特定多数のユーザーがアクセスする環境でも、安全かつ確実にファイルのアップロードと後続処理を行うことができます。