始める
開発者ガイド
Reactアップローダーの作成

imgixを使ったReactアップローダーの作成

Reactとimgixセッションエンドポイントを使用して、ユーザーがimgixアカウントに画像をアップロードできるインターフェースを構築します。このガイドでは、5GBまでの大容量ファイルのアップロードをサポートするために、アップロードセッションを使用します。

チュートリアルの完成したコードとデモは、このCodeSandbox (opens in a new tab)にあります。

デモ

The Session Status is: No Status

前提条件

手順

手順1: Reactプロジェクトのセットアップ

まず、以下のコマンドを使用して新しいReactプロジェクトを作成します。

npx create-react-app imgix-uploader
cd imgix-uploader

次に、必要な依存関係をインストールします。

npm install axios react-imgix

srcディレクトリにReactUploader.jsという新しいコンポーネントを作成しましょう。このコンポーネントは、ファイルの選択からimgixへの送信まで、画像のアップロードプロセス全体を処理します。

インストールと設定が完了すると、ディレクトリは次のようになります(他のファイルも含まれる可能性があります)。

    • package.json
  • 手順3: ReactUploader.jsコンポーネントの初期要素を作成する

    まず、ReactUploader.jsコンポーネントにフォーム要素を作成しましょう。これらの要素は、画像をアップロードするためのユーザーインターフェースとなります。

    また、必要な依存関係をインポートし、コンポーネントの初期状態を設定します。

    作成するフォームには、imgix APIキー (opens in a new tab)Source IDが必要です。

    import { useState, useEffect } from "react"
    import axios from "axios"
    import Imgix from "react-imgix"
     
    export default function ReactUploader() {
      return (
        <div>
          <form className="mb-4" onSubmit={handleSubmit}>
            {/* APIキー */}
            <input
              type="text"
              placeholder="Your imgix API key"
              value={apiKey}
              onChange={(e) => setApiKey(e.target.value)}
            />
            {/* Source ID */}
            <input
              type="text"
              placeholder="Source ID"
              value={sourceId}
              onChange={(e) => setSourceId(e.target.value)}
            />
            {/* imgixドメイン名 */}
            <input
              type="text"
              placeholder="your_subdomain.imgix.net"
              value={imgixDomain}
              onChange={(e) => setImgixDomain(e.target.value)}
            />
            {/* 画像をアップロードするパス */}
            <input
              type="text"
              placeholder="path/to/upload/to/"
              onBlur={(e) => {
                // アップロードパスを解析して末尾のスラッシュを削除します
                let parsedPath = ""
                if (uploadPath.charAt(0) !== "/" && uploadPath.length > 1) {
                  parsedPath = "/" + uploadPath
                } else {
                  parsedPath = uploadPath
                }
                if (uploadPath.charAt(uploadPath.length - 1) !== "/") {
                  parsedPath += "/"
                }
                setUploadPath(parsedPath)
              }}
              value={uploadPath}
              onChange={(e) => setUploadPath(e.target.value)}
            />
            {/* 画像アップロード */}
            <input type="file" onChange={(e) => setImg(e.target.files[0])} />
            <button disabled={disableForm}>Upload Image</button>
          </form>
          {/* ステータス情報はここに表示されます */}
          <div>
            <h3>セッションのステータスは: {sessionStatus}</h3>
            <div>
              {sessionStatus === "ERROR" && <h3>{error}</h3>}
              {/* セッションが完了したら、imgix画像を表示します */}
              {sessionStatus === "COMPLETE" && (
                <Imgix
                  src={imgixUrl}
                  width={200}
                  height={200}
                  imgixParams={{ auto: "format,compress,enhance", fit: "crop" }}
                />
              )}
            </div>
            {sessionStatus === "COMPLETE" && <h4>{imgixUrl}</h4>}
          </div>
        </div>
      )
    }

    手順4: フォームハンドラーの実装

    フォームが設定されたので、フォームの送信を処理し、画像をimgix APIに送信するロジックを実装しましょう。

    Reactの状態管理

    フォームデータとアップロードセッションのステータスを管理するために、Reactの状態管理を使用します。Reactの状態管理についての詳細は、Reactのドキュメント (opens in a new tab)を参照してください。

    export default function ReactUploader() {
      const [img, setImg] = useState()
      const [sessionStatus, setSessionStatus] = useState("No Status")
      const [imgixUrl, setImgixUrl] = useState()
      const [apiKey, setApiKey] = useState("")
      const [sourceId, setSourceId] = useState("")
      const [imgixDomain, setImgixDomain] = useState("")
      const [uploadPath, setUploadPath] = useState("")
      const [sessionId, setSessionId] = useState("")
      const [presignedUrl, setPresignedUrl] = useState("")
      const [error, setError] = useState("")
      const [disableForm, setDisableForm] = useState(false)
     
      return {
        /* 手順1のフォーム要素 */
      }
    }

    フォームハンドラー (handleSubmit)

    フォームが送信されたときにhandleSubmit関数がトリガーされます。この関数はバリデーションを処理し、アップロードセッションを作成し、アップロードのためのデータを準備します。

    export default function ReactUploader() {
      // 手順2と3のインポート文と状態変数
     
      // フォームの送信を処理する関数
      const handleSubmit = async (e) => {
        e.preventDefault()
     
        // エラーハンドリング
        if (!img) {
          alert("アップロードする画像を選択してください")
          return
        } else if (!apiKey) {
          alert("imgix APIキーを入力してください")
        } else if (!sourceId) {
          alert("ソースIDを入力してください")
        }
     
        setDisableForm(true)
        setSessionStatus("OPENING")
     
        //セッションを作成してセッションIDを設定
        await axios({
          method: "POST",
          url:
            `https://api.imgix.com/api/v1/sources/${sourceId}/upload-sessions/create` +
            uploadPath +
            img.name,
          maxBodyLength: Infinity,
          headers: {
            "Content-Type": "application/vnd.api+json",
            Authorization: `Bearer ${apiKey}`,
          },
        })
          .then((response) => {
            setSessionId(response.data.data.id)
            setSessionStatus(response.data.data.attributes.status)
            setPresignedUrl(response.data.data.attributes.url)
          })
          .catch((error) => {
            // サーバーエラーハンドリング
            console.log(error?.response?.data?.errors[0]?.detail)
            setSessionStatus("ERROR")
            setError(error?.response?.data?.errors[0]?.detail)
            console.log(error.message)
          })
      }
     
      return {
        /* 手順1のフォーム要素 */
      }
    }
    handleSubmitの主な手順

    バリデーション: この関数は、画像、APIキー、およびソースIDが提供されているかどうかをチェックします。また、アップロードパスを解析します。これらが欠けている場合、ユーザーに警告し、実行を停止します。

    フォームの無効化: フォームは無効化され(setDisableForm(true))、現在の送信が処理されている間、さらに送信できないようにします。

    アップロードセッションの作成: ファイル名、ソースID、および画像を保存するパスを含むAPIリクエストがimgixに送信され、新しいアップロードセッションが作成されます。成功すると、セッションID、セッションステータス、および画像をアップロードするためのプリサインURLが保存されます。

    手順5: useEffectを使用してアップロードプロセスを管理する

    アップロードセッションが正常に作成されると、useEffect (opens in a new tab)フックがsessionStatusを監視し、実際の画像アップロードを処理します。また、アップロードが完了したときやエラーが発生したときに状態を変更します。

    export default function ReactUploader() {
     
      // 手順2と3のインポート文と状態変数
     
      useEffect(() => {
        //セッションIDから取得したプリサインURLを使用して画像をアップロードします
        // ドキュメント: https://docs.imgix.com/apis/management/assets#using-upload-sessions
        if (sessionStatus === "PENDING") {
          axios({
            method: "PUT",
            url: presignedUrl,
            headers: {
                      "Content-Type": "application/octet-stream",
                    },
            data: img,
                  }
                )
            .then(() => {
              // 画像がアップロードされたら、セッションを閉じて完了状態を設定します
              closeSession(sessionId)
              setSessionStatus("COMPLETE")
              setImgixUrl("https://" + imgixDomain + uploadPath + img.name)
              setDisableForm(false)
            })
            .catch((error) => {
              // エラーが発生した場合、エラーハンドラを設定します
              closeSession(sessionId)
              setSessionStatus("ERROR")
              console.log(error.message)
              setDisableForm(false)
            })
        }
     
        // エラーやアップロード時にセッションを閉じる関数
        const closeSession = (sessionId) => {
          // セッションを閉じます
          axios({
            method: "POST",
            url:
            `https://api.imgix.com/api/v1/sources/${sourceId}/upload-sessions/close/` +
            sessionId,
            headers: {
                      "Content-Type": "application/vnd.api+json",
                      Authorization: `Bearer ${apiKey}`,
                    },
                  }
          )
          .catch((error) => {
            console.log(error)
          })
        }
      }, [sessionStatus, error])
     
      // 手順4のhandleSubmit関数
     
      return (
        // 手順1のフォーム要素
     )
    }

    useEffectの主な手順

    sessionStatusの監視: useEffectフックは、sessionStatusが変更されるたびに実行されます。ステータスが「PENDING」の場合、アップロードが進行します。

    画像のアップロード: HTTP PUTリクエストがプリサインURLに送信され、選択された画像がアップロードされます。Content-Typeはバイナリデータをアップロードするため、application/octet-streamに設定されます。

    成功またはエラーの処理: 成功時には、セッションが閉じられ、画像URLが保存されます。エラー時には、セッションが閉じられ、フォームが再び有効になります。

    手順6: コンポーネントをアプリケーションに統合する

    ReactUploaderコンポーネントが完成したので、メインアプリケーションに統合しましょう。src/App.jsを開き、以下の内容に置き換えます。

    import React from "react"
    import ReactUploader from "./ReactUploader"
     
    function App() {
      return (
        <div className="App">
          <h1>imgixで画像をアップロード</h1>
          <ReactUploader />
        </div>
      )
    }
     
    export default App

    手順7: アプリケーションを実行する

    画像アップローダーを実際に動作させるために、ターミナルで次のコマンドを実行します。

    npm start

    これでアプリはhttp://localhost:3000で実行され、imgixに画像をアップロードできるようになります。 (opens in a new tab)

    結論

    このチュートリアルでは、imgix APIに画像をアップロードするシンプルなReactアプリケーションを作成しました。このアプリは、エラーハンドリングの強化、動的APIキー管理、より高度な画像処理など、追加機能を追加して拡張することができます。また、セッションの作成や画像のアップロードをサーバー側で処理することで、ユーザーのAPIキー入力を不要にすることもできます。

    注: これは、APIキーとSource IDを入力する必要がある簡略化されたデモです。実際のアプリケーションでは、これらが既に指定されているはずです。

    さらに、クライアント側で資格情報を扱うのは推奨されません。資格情報は悪意のあるアクターに露出する可能性があるためです。APIキーやその他の機密情報が安全に保存され、クライアントに露出しないようにしてください。APIキーを安全に扱う方法はいくつかあり、サーバーレス機能やバックエンドサーバーにリクエストを送信して、クライアント側からimgixにリクエストを送信する代わりに画像のアップロードを処理することが挙げられます。