imgixを使ったReactアップローダーの作成
Reactとimgixセッションエンドポイントを使用して、ユーザーがimgixアカウントに画像をアップロードできるインターフェースを構築します。このガイドでは、5GBまでの大容量ファイルのアップロードをサポートするために、アップロードセッションを使用します。
チュートリアルの完成したコードとデモは、このCodeSandboxにあります。
デモ
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キーと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のドキュメントを参照してください。
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
フックが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に画像をアップロードできるようになります。
結論
このチュートリアルでは、imgix APIに画像をアップロードするシンプルなReactアプリケーションを作成しました。このアプリは、エラーハンドリングの強化、動的APIキー管理、より高度な画像処理など、追加機能を追加して拡張することができます。また、セッションの作成や画像のアップロードをサーバー側で処理することで、ユーザーのAPIキー入力を不要にすることもできます。
注: これは、APIキーとSource IDを入力する必要がある簡略化されたデモです。実際のアプリケーションでは、これらが既に指定されているはずです。
さらに、クライアント側で資格情報を扱うのは推奨されません。資格情報は悪意のあるアクターに露出する可能性があるためです。APIキーやその他の機密情報が安全に保存され、クライアントに露出しないようにしてください。APIキーを安全に扱う方法はいくつかあり、サーバーレス機能やバックエンドサーバーにリクエストを送信して、クライアント側からimgixにリクエストを送信する代わりに画像のアップロードを処理することが挙げられます。