====== DAppsからIPFSにファイルをアップロードする ====== React で Web アプリケーションを実装し、HTML の FILE API で指定されたファイルを IPFS にアップロードする機能を実現します。 ===== React プロジェクトの作成 ===== > mkdir IPFS > cd IPFS IPFS> npx create-react-app ipfs-web --template typescript IPFS> cd .\ipfs-web\ IPFS\ipfs-web> npm install --save ipfs-core ipfs-core-types util 「[[https://github.com/ipfs/js-ipfs|ipfs-core]]」は JavaScript で IPFS を操作するためのライブラリ js-ipfs の一部です。 ===== 参考 ===== * [[https://github.com/ipfs-examples/js-ipfs-examples|js-ipfs-examples]] * [[https://github.com/ipfs/js-ipfs/tree/master/docs/core-api|IPFS Core API]] ===== IPFSUploader.tsx の実装 ===== IPFS にファイルをアップロードする機能を提供する IPFSUploader.tsx コンポーネントを実装します。 IPFS\ipfs-web> mkdir src\components IPFS\ipfs-web> code src\components\IPFSUploader.tsx import React, { useState, useEffect } from 'react'; import type { IPFS } from 'ipfs-core-types'; import * as IPFSCore from 'ipfs-core'; let ipfs: IPFS; function IPFSUploader() { const [isIpfsReady, setIpfsReady] = useState(Boolean(ipfs)) const [version, setVersion] = useState(""); const [cid, setCID] = useState(""); useEffect(() => { startIpfs(); return function cleanup () { if (ipfs && ipfs.stop) { console.log('Stopping IPFS'); ipfs.stop().catch((err: any) => console.error(err)); //ipfs = undefined; setIpfsReady(false); } } }, []); const startIpfs = async () => { if(ipfs){ console.log('IPFS already started'); /* } else if (window.ipfs && window.ipfs.enable) { console.log('Found window.ipfs') ipfs = await window.ipfs.enable({ commands: ['id'] }) */ } else { ipfs = await IPFSCore.create(); console.log("IPFS Started"); const _version = await ipfs.version(); setVersion(_version.version); } setIpfsReady(Boolean(ipfs)); }; const fileSelected = async (event: React.ChangeEvent) => { if(!isIpfsReady) return; const targetFile = event.target.files?.[0]; if(targetFile){ const _result = await ipfs.add(targetFile); //const _result = await ipfs.add('Hello world'); setCID(_result.path); } }; return (

IPFS File Uploader

IPFS(ipfs-core) Version: { version }

Uploaded File CID: { cid }

open browser

open ipfs.io public gateway

); } export default IPFSUploader;
===== App.tsx に IPFSUploader を追加 ===== IPFS\ipfs-web> code src\App.tsx 不要な記述を削除し、IPFSUploader コンポーネントを追加します。 import React from 'react'; import './App.css'; import IPFSUploader from './components/IPFSUploader'; function App() { return (
); } export default App;
===== 実行 ===== IPFS\ipfs-web> npm start ===== IPFSDirectoryUploader ===== MFS を利用してファイルをアップロードする。 IPFS\ipfs-web> code src\components\IPFSDirectoryUploader.tsx import React, { useState, useEffect } from 'react'; import type { IPFS } from 'ipfs-core-types'; import * as IPFSCore from 'ipfs-core'; import { MFSEntry } from 'ipfs-core-types/dist/src/files/index'; let ipfs: IPFS; function IPFSDirectoryUploader() { const [isIpfsReady, setIpfsReady] = useState(Boolean(ipfs)) const [version, setVersion] = useState(""); const [MFSEntlies, setMFSEntlies] = useState(); useEffect(() => { startIpfs(); return function cleanup () { if (ipfs && ipfs.stop) { console.log('Stopping IPFS'); ipfs.stop().catch((err: any) => console.error(err)); //ipfs = undefined; setIpfsReady(false); } } }, []); const startIpfs = async () => { if(ipfs){ console.log('IPFS already started'); /* } else if (window.ipfs && window.ipfs.enable) { console.log('Found window.ipfs') ipfs = await window.ipfs.enable({ commands: ['id'] }) */ } else { ipfs = await IPFSCore.create(); console.log("IPFS Started"); const _version = await ipfs.version(); setVersion(_version.version); const lsResult = await ipfs.files.ls("/"); let uploadDirectoryExist = false; for await (const file of lsResult){ if(file.name === "upload-directory"){ console.log("/upload-directory is already exist."); uploadDirectoryExist = true; } } if(!uploadDirectoryExist){ console.log("mkdir /upload-directory"); await ipfs.files.mkdir("/upload-directory"); } } setIpfsReady(Boolean(ipfs)); }; const fileSelected = async (event: React.ChangeEvent) => { if(!isIpfsReady) return; const targetFile = event.target.files?.[0]; if(targetFile){ const fileReader = new window.FileReader(); fileReader.readAsArrayBuffer(targetFile); fileReader.onloadend = async () => { let ab = fileReader.result as ArrayBuffer; const u8a = new Uint8Array(ab); console.log(`upload /upload-directory/${targetFile.name}`); await ipfs.files.write(`/upload-directory/${targetFile.name}`, u8a, {create: true}); await ls("/upload-directory"); }; } }; const ls = async (path: string) => { const lsResult = await ipfs.files.ls(path); for await (const file of lsResult){ console.log(`${file.name}: ${file.cid.toString()}`); } }; const MFSStat = async () => { if(!isIpfsReady) return; const lsResult = await ipfs.files.ls('/upload-directory'); let _mfs_entlies: MFSEntry[] = []; for await (const file of lsResult){ console.log(`${file.name}: ${file.cid.toString()}`); _mfs_entlies.push(file); } setMFSEntlies(_mfs_entlies); }; return (

IPFS File Uploader

IPFS(ipfs-core) Version: { version }

{ MFSEntlies?.map((file) => (

{file.name}: {file.cid.toString()}

Open IPFS img link.

))}

); } export default IPFSDirectoryUploader;
App.tsx に IPFSDirectoryUploader コンポーネントを記述する。