const onDrop = (acceptedFiles: File[]) => {
console.log(formData)
}
return (
<div>
<DropZone onDrop={onDrop}>
{({getRootProps, isDragActive}) => (
<div {...getRootProps()}>
{isDragActive ? "Drop it like it's hot!" : 'Drag a file to upload!'}
</div>
)}
</DropZone>
</div>
)
react-dropzoneを使ってこんな感じに書いて、描画された部分に画像をドロップしてみると
lastModified: 1571463132902
lastModifiedDate: Sat Oct 19 2019 14:32:12 GMT+0900 (日本標準時) {}
name: "hoge.PNG"
path: "hoge.PNG"
size: 353348
type: "image/png"
webkitRelativePath: ""
こんな感じのFileっていう型の配列がもらえる。
んじゃあこのデータ配列そのままサーバ側にぶん投げて、サーバ側でfirebase storageにpath指定してあげりゃあ画像のアップロード実装できんじゃん!
って思ってたんだけど、見てわかる通りpathがfullpath(?)になってない。どうしよう...
最終的に、サーバ側に一時的に画像を保存して、そこで生成されたpathをfirebase側に指定してあげたらうまく行った。
そのために、まずはreact-dropzoneから受け取ったFile配列をFormDataとやらに変換して、それをPOSTデータとしてぶん投げた。
const onDrop = (acceptedFiles: File[]) => {
const formData = new FormData();
acceptedFiles.forEach(file => {
formData.append('Files', file)
})
dispatch(postFiles.request(formData))
}
参考にさせていただいたサイト様様 → https://qiita.com/uryyyyyyy/items/9954205a620b6f3c1f24
んで、これをExpress側で受け取るんだけど、このデータはmultipart/form-dataというものらしく、普通にやったらうまく受け取れなかった。なんやそれ。知らんがな。
import multer from 'multer';
const upload = multer({ dest: './uploads/' });
app.post('/files', upload.fields([ { name: 'Files' } ]), postStorageController);
export function postStorageController(req: Request, res: Response, next: NextFunction) {
const files: Express.Multer.File[] = req.files['Files'];
こういう風に書いてあげると、filesの部分で以下のような感じで値がもらえる
[Object: null prototype] {
Files:
[ { fieldname: 'Files',
originalname: 'hoge.PNG',
encoding: '7bit',
mimetype: 'image/png',
destination: 'uploads/',
filename: 'd18eb9674f13a81898e7c25bb0c3bda6',
path: 'uploads/d18eb9674f13a81898e7c25bb0c3bda6',
size: 353348 } ] }
参考にさせていただいたサイト様様 → https://qiita.com/uryyyyyyy/items/9954205a620b6f3c1f24
(さっきと同じ記事。圧倒的感謝)
あとは、Google先生の解説を見ながらfirebase storageにあげれば終わり!
export function postStorageController(req: Request, res: Response, next: NextFunction) {
const files: Express.Multer.File[] = req.files['Files'];
files.forEach(fileInfo => {
const uploadFilePath = `files/${fileInfo.originalname}`
bucket.upload(fileInfo.path, { destination: uploadFilePath, contentType: fileInfo.mimetype }, error => {
if (error) {
console.log(`failed storage post ${fileInfo.originalname}`);
console.log(error.message);
return res.sendStatus(404);
} else {
console.log(`success storage post ${fileInfo.originalname}`);
return res.sendStatus(200);
}
}
}
↓↓↓今回書いたソースコード
(フロント)
https://github.com/ShotaroOkada/fileupload_react_client
(サーバ)
https://github.com/ShotaroOkada/fileupload_express_api