こんばんは。
今日は「ReactでJSZipを使用したファイルアップロード」について説明いたします。
必要なパッケージのインストール
npm install jszip
Reactコンポーネントの作成
JSZip
ライブラリを使用して、アップロードされたZIP
ファイルの内容を読み取り、表示するコンポーネントを作成します。
import React, { useState } from 'react';
import JSZip from 'jszip';
function ZipFileUploader() {
const [filesList, setFilesList] = useState([]);
const handleFileUpload = async (event) => {
const file = event.target.files[0];
if (file) {
const zip = new JSZip();
try {
const content = await file.arrayBuffer();
const loadedZip = await zip.loadAsync(content);
const files = [];
loadedZip.forEach((relativePath, zipEntry) => {
files.push(relativePath);
});
setFilesList(files);
} catch (error) {
console.error('ZIPファイルの読み込み中にエラーが発生しました:', error);
}
}
};
return (
<div>
<h1>ZIPファイルのアップロードと内容表示</h1>
<input type="file" accept=".zip" onChange={handleFileUpload} />
<h2>ファイル一覧:</h2>
<ul>
{filesList.map((fileName, index) => (
<li key={index}>{fileName}</li>
))}
</ul>
</div>
);
}
export default ZipFileUploader;
コードの説明
- ファイルアップロードハンドラー (
handleFileUpload
)- ユーザーがファイルを選択すると呼び出されます。
- 選択されたファイルが存在するか確認します。
-
JSZip
のインスタンスを作成し、ファイルの内容をarrayBuffer
として読み込みます。 -
zip.loadAsync
を使用して、ZIPファイルの内容を非同期的にロードします。 -
loadedZip.forEach
を使用して、ZIP
内の各ファイルにアクセスし、ファイル名を配列に保存します。 -
setFilesList
を使用して状態を更新し、画面にファイル一覧を表示します。
- ファイル一覧の表示
-
filesList
の状態をループして、ファイル名を- リストとして出力します。
-
追加機能の実装
ファイル内容の表示
テキストファイルや画像の場合、ファイルの内容を読み込んで画面に表示できます。
zipEntry.async("text")
またはzipEntry.async("base64")
を使用してファイル内容を取得します。
// テキストファイルの内容を読み込む例
const handleFileUpload = async (event) => {
// 前述のコードと同じ
const filesContent = [];
loadedZip.forEach(async (relativePath, zipEntry) => {
if (!zipEntry.dir) {
const content = await zipEntry.async('text');
filesContent.push({ name: relativePath, content });
setFilesList([...filesContent]);
}
});
};
// レンダリング部分でファイル内容も表示
<ul>
{filesList.map((file, index) => (
<li key={index}>
<h3>{file.name}</h3>
<pre>{file.content}</pre>
</li>
))}
</ul>
画像ファイルの表示
画像の場合、base64
またはblob
形式で読み込み、<img>
タグに挿入できます。
// 画像ファイルを読み込む例
if (zipEntry.name.match(/\.(png|jpe?g|gif)$/)) {
const content = await zipEntry.async('base64');
filesContent.push({
name: relativePath,
content: `data:image/*;base64,${content}`,
});
}
// レンダリング部分で画像を表示
{filesList.map((file, index) => (
<div key={index}>
<h3>{file.name}</h3>
{file.content.startsWith('data:image') ? (
<img src={file.content} alt={file.name} />
) : (
<pre>{file.content}</pre>
)}
</div>
))}
注意事項
- 非同期処理
-
forEach
内で非同期関数を使用する場合、Promise.all
を使用して全てのファイルを処理した後に状態を更新するのが良いです。
-
- 大容量ファイルの処理
- 大きなファイルや多数のファイルを処理する際は、パフォーマンスに注意が必要です。
- セキュリティ問題
- アップロードされたファイルの内容をそのまま表示すると、
XSS
攻撃のリスクがあるため、内容を適切にエスケープするか、信頼できるファイルのみを処理する必要があります。
- アップロードされたファイルの内容をそのまま表示すると、
全体のコード
import React, { useState } from 'react';
import JSZip from 'jszip';
function ZipFileUploader() {
const [filesList, setFilesList] = useState([]);
const handleFileUpload = async (event) => {
const file = event.target.files[0];
if (file) {
const zip = new JSZip();
try {
const content = await file.arrayBuffer();
const loadedZip = await zip.loadAsync(content);
const filesContent = [];
await Promise.all(
Object.keys(loadedZip.files).map(async (filename) => {
const zipEntry = loadedZip.files[filename];
if (!zipEntry.dir) {
if (zipEntry.name.match(/\.(png|jpe?g|gif)$/)) {
const content = await zipEntry.async('base64');
filesContent.push({
name: zipEntry.name,
type: 'image',
content: `data:image/*;base64,${content}`,
});
} else {
const content = await zipEntry.async('text');
filesContent.push({
name: zipEntry.name,
type: 'text',
content,
});
}
}
})
);
setFilesList(filesContent);
} catch (error) {
console.error('ZIPファイルの読み込み中にエラーが発生しました:', error);
}
}
};
return (
<div>
<h1>ZIPファイルのアップロードと内容表示</h1>
<input type="file" accept=".zip" onChange={handleFileUpload} />
<h2>ファイル一覧:</h2>
{filesList.map((file, index) => (
<div key={index}>
<h3>{file.name}</h3>
{file.type === 'image' ? (
<img src={file.content} alt={file.name} />
) : (
<pre>{file.content}</pre>
)}
</div>
))}
</div>
);
}
export default ZipFileUploader;
上記のコードは、ユーザーがZIPファイルをアップロードすると、その内容を読み込んで画面に表示するReactコンポーネントです。テキストファイルは<pre>
タグで、画像ファイルは<img>
タグで表示します。
参考事項
- セキュリティ: 実際のアプリケーションでは、アップロードされたファイルに対する厳密な検証とセキュリティ対策が必要です。
- エラーハンドリング: ユーザーに明確なエラーメッセージを提供するために、追加のエラーハンドリングを実装することをお勧めします。
- スタイリング: 必要に応じて、CSSを使用してコンポーネントのデザインを改善できます。
今日は以上です。
ありがとうございました。
よろしくお願いいたします。