0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

AWS S3って何?ファイル保存が劇的に楽になった話

Posted at

はじめに

「ユーザーが画像をアップロードする機能を作りたいけど、サーバーの容量が心配...」
「ファイルのバックアップ、どうやって管理すればいいの?」

そんな悩みを解決してくれるのがAWS S3です。

今回は「S3って聞いたことあるけど、結局何なの?」という方向けに、S3の基本から実際の使い方まで、わかりやすく解説してみます!

AWS S3って何?

S3(Simple Storage Service)は、Amazon Web Servicesが提供するクラウドストレージサービスです。

身近な例で説明

GoogleドライブDropboxのプログラマー版だと思ってください。

  • 個人用クラウドストレージ: 写真や文書を保存
  • S3: プログラムが使うファイルを保存

違いは何?

  • 容量がほぼ無制限
  • API経由でプログラムから操作できる
  • 世界中どこからでも高速アクセス
  • 堅牢性がハンパない(99.999999999%の耐久性)

なんでS3がいいの?

1. 容量を気にしなくていい

従来のサーバー:

サーバー容量: 100GB
「あー、もうすぐ容量いっぱい...HDDを増設しないと」

S3の場合:

使った分だけ課金
「容量?気にしたことないです」

2. バックアップが自動

従来:

「定期的にバックアップ取らないと...」
「バックアップHDDが壊れた...」

S3:

自動で複数の場所にコピー保存
「データが消える?まずありえないです」

3. CDN(高速配信)が使える

従来:

「海外のユーザーには画像表示が遅い...」

S3 + CloudFront:

「世界中どこでも高速表示!」

基本概念の説明

バケット = フォルダ

S3では、ファイルを「バケット」という入れ物に保存します。

my-app-bucket/          ← バケット名
├── images/
│   ├── user-avatars/
│   │   ├── user1.jpg
│   │   └── user2.png
│   └── product-photos/
│       ├── product1.jpg
│       └── product2.jpg
├── documents/
│   └── terms.pdf
└── backup/
    └── database-backup.sql

キー = ファイルパス

各ファイルには「キー」という名前が付きます:

images/user-avatars/user1.jpg  ← これがキー

普通のファイルパスと同じ感覚です。

実際に使ってみよう

1. バケットを作る

AWS Consoleで作成:

  1. AWS Consoleにログイン
  2. S3サービスを選択
  3. 「バケットを作成」をクリック
  4. バケット名を入力(全世界で一意でないとダメ)
  5. リージョンを選択(日本ならap-northeast-1

バケット名の例:

✅ good: my-app-images-2024
✅ good: company-backups-prod
❌ bad: images (すでに使われてる)
❌ bad: My App Images (大文字・スペースダメ)

2. Node.jsからS3を操作

// まずライブラリをインストール
// npm install @aws-sdk/client-s3

const { S3Client, PutObjectCommand, GetObjectCommand } = require('@aws-sdk/client-s3');

// S3クライアントを作成
const s3Client = new S3Client({ 
  region: 'ap-northeast-1',
  credentials: {
    accessKeyId: 'YOUR_ACCESS_KEY',
    secretAccessKey: 'YOUR_SECRET_KEY'
  }
});

// ファイルをアップロード
async function uploadFile(bucketName, fileName, fileContent) {
  try {
    const command = new PutObjectCommand({
      Bucket: bucketName,
      Key: fileName,
      Body: fileContent,
      ContentType: 'image/jpeg' // ファイルの種類
    });
    
    const result = await s3Client.send(command);
    console.log('アップロード成功:', result);
    
    // 公開URLを生成
    const url = `https://${bucketName}.s3.ap-northeast-1.amazonaws.com/${fileName}`;
    return url;
  } catch (error) {
    console.error('アップロード失敗:', error);
  }
}

// 使用例
uploadFile('my-app-images', 'users/avatar.jpg', imageBuffer);

3. Express.jsでファイルアップロード機能

const express = require('express');
const multer = require('multer'); // ファイルアップロード用
const { S3Client, PutObjectCommand } = require('@aws-sdk/client-s3');

const app = express();
const upload = multer(); // メモリに一時保存

const s3Client = new S3Client({ region: 'ap-northeast-1' });

// ファイルアップロードのエンドポイント
app.post('/upload', upload.single('image'), async (req, res) => {
  try {
    if (!req.file) {
      return res.status(400).json({ error: 'ファイルが選択されていません' });
    }
    
    // S3にアップロード
    const fileName = `images/${Date.now()}-${req.file.originalname}`;
    const command = new PutObjectCommand({
      Bucket: 'my-app-bucket',
      Key: fileName,
      Body: req.file.buffer,
      ContentType: req.file.mimetype
    });
    
    await s3Client.send(command);
    
    // 成功レスポンス
    const fileUrl = `https://my-app-bucket.s3.amazonaws.com/${fileName}`;
    res.json({ 
      message: 'アップロード成功',
      url: fileUrl 
    });
    
  } catch (error) {
    console.error('アップロードエラー:', error);
    res.status(500).json({ error: 'アップロードに失敗しました' });
  }
});

4. Reactでファイルアップロード

import React, { useState } from 'react';

function FileUpload() {
  const [file, setFile] = useState(null);
  const [uploading, setUploading] = useState(false);
  const [uploadedUrl, setUploadedUrl] = useState('');

  const handleFileSelect = (event) => {
    setFile(event.target.files[0]);
  };

  const handleUpload = async () => {
    if (!file) return;

    setUploading(true);
    
    const formData = new FormData();
    formData.append('image', file);

    try {
      const response = await fetch('/upload', {
        method: 'POST',
        body: formData
      });
      
      const result = await response.json();
      setUploadedUrl(result.url);
      alert('アップロード成功!');
    } catch (error) {
      alert('アップロード失敗...');
    } finally {
      setUploading(false);
    }
  };

  return (
    <div>
      <input 
        type="file" 
        accept="image/*" 
        onChange={handleFileSelect}
      />
      <button 
        onClick={handleUpload} 
        disabled={!file || uploading}
      >
        {uploading ? 'アップロード中...' : 'アップロード'}
      </button>
      
      {uploadedUrl && (
        <div>
          <p>アップロード完了:</p>
          <img src={uploadedUrl} alt="アップロード画像" style={{maxWidth: '300px'}} />
        </div>
      )}
    </div>
  );
}

S3の料金体系

基本料金(東京リージョン)

  • ストレージ料金: 1GBあたり約3円/月
  • リクエスト料金: 1000回あたり約0.5円
  • データ転送料金: 1GBあたり約10円

実際の例:

100MB の画像ファイル × 1000枚 = 100GB
月額料金: 100GB × 3円 = 約300円

1日1000回のアクセス × 30日 = 30,000回
リクエスト料金: 30,000回 × 0.0005円 = 約15円

合計: 約315円/月

小さなアプリなら、月数百円程度で運用できます!

セキュリティ・権限設定

1. バケットポリシー

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": "*",
      "Action": "s3:GetObject",
      "Resource": "arn:aws:s3:::my-public-bucket/*"
    }
  ]
}

意味: このバケットの中身は誰でも見ることができる(公開設定)

2. プライベートファイルの一時公開URL

const { getSignedUrl } = require('@aws-sdk/s3-request-presigner');

// 1時間だけ有効なダウンロードURL
async function generateDownloadUrl(bucketName, fileName) {
  const command = new GetObjectCommand({
    Bucket: bucketName,
    Key: fileName
  });
  
  const url = await getSignedUrl(s3Client, command, { expiresIn: 3600 }); // 1時間
  return url;
}

よくある使い方パターン

1. ユーザープロフィール画像

// アップロード時にファイル名をリネーム
const fileName = `profiles/${userId}-${Date.now()}.jpg`;

2. 静的サイトホスティング

// HTMLファイルをS3に置いて、Webサイトとして公開
// バケット設定で「Static website hosting」を有効にするだけ

3. ログファイルの保存

// アプリケーションログを日付別に保存
const logFileName = `logs/${new Date().toISOString().split('T')[0]}.log`;

つまずきやすいポイント

1. CORS(Cross-Origin)エラー

ブラウザから直接S3にアクセスする時:

[
  {
    "AllowedHeaders": ["*"],
    "AllowedMethods": ["GET", "PUT", "POST"],
    "AllowedOrigins": ["https://myapp.com"],
    "ExposeHeaders": []
  }
]

2. 権限エラー

「Access Denied」が出る時:

  • IAMユーザーにS3の権限があるか確認
  • バケットポリシーが正しいか確認
  • リージョンが合ってるか確認

3. ファイル名の日本語

// 日本語ファイル名はエンコードが必要
const encodedFileName = encodeURIComponent('日本語ファイル名.jpg');

まとめ

AWS S3は、最初は「難しそう...」と思うかもしれませんが、基本的な使い方は意外と簡単です。

S3を使うメリット:

  • サーバーの容量を気にしなくていい
  • 自動バックアップで安心
  • 世界中から高速アクセス
  • 使った分だけ課金で経済的

こんな時に使おう:

  • ユーザーのプロフィール画像
  • 商品の写真
  • PDFファイルのダウンロード機能
  • ログファイルの保管
  • 静的サイトのホスティング

最初は「ファイルアップロード機能」から始めて、慣れてきたらCDN(CloudFront)との組み合わせとかも試してみてください。

クラウドサービスって最初は敷居が高く感じますが、使い始めると「なんで今まで使わなかったんだろう」って思いますよ!☁️

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?