📂
初心者すぎてNext.jsでform-dataのファイルアップロードを実装した時のハマったとこ
メインはバックエンド、副業でフロントエンドエンジニアをしていてCSSは万年初心者のmikiです。
仕事でapi側でファイルアップロードを実装する時にハマったことがあったのでメモかねて。
タイトルではform-dataで実装とありますが最初は2パターンのファイルを送信する実装を考えました。
-
form-data
で送信する -
base64
に変換して送信する
base64は文字列にしてるので扱いやすいですが。デコードとエンコードが面倒でコストかかるなという印象。サイズも大きくなりがちなのでとりあえずform-dataを採用することにしました。
どちらかというとform-dataが王道ではある気がしますが、base64変換する方もそれなりに実装を見かけることはあるので、扱わないといけないデータ&保存方法によって比較して見るのがいいかなとかそんな感じです。
form-data
送信の実装サンプル
フロントエンド
import axios from "axios";
export default function Images() {
const handleUploadClick = async (e) => {
const file = e.target.files[0];
const formData = new FormData();
formData.append('file', file);
try {
await axios.post(`アップロード先エンドポイント`,
formData
);
} catch (e) {
console.error(e);
}
};
return (
<div style={{ padding: 20 }}>
<label htmlFor="upload-button" style={{ border: "1px solid #222", borderRadius: 10, padding: 10, cursor: "pointer" }}>
<input
accept="image/*"
id="upload-button"
type="file"
onChange={handleUploadClick}
hidden
/>
Choose file
</label>
</div >
);
};
バックエンド
const formidable = require("formidable");
// これ必要なことに気づかなかった↓
export const config = {
api: {
bodyParser: false,
},
};
export default async (req, res) => {
if (req.method !== "POST") return;
const form = new formidable.IncomingForm();
form.parse(req, async function (err, fields, files) {
if (err) {
res.statusCode = 500;
res.json({
method: req.method,
error: err
});
res.end();
return;
}
const file = files.file;
// ファイルをなんやかんやする
});
};
しばらく気づかなかったハマりポイント
ここのconfig部分なしで最初実装していたんですが
// これ必要なことに気づかなかった↓
export const config = {
api: {
bodyParser: false,
},
};
ファイルがパースされなくてなんでだろう?と思ってしばらく考えていました。どうもnextjsはデフォルトでrrequest.body
をパースしてくれるようで。。。
そのためストリームでファイルが受信できなかったみたいです。
というわけでNext.jsのAPIミドルウェアのページを見ると・・・
bodyParser is automatically enabled. If you want to consume the body as a Stream or with raw-body, you can set this to false.
なるほど。
これでストリームでファイルが受けれるようになりました!Happy!🥳
Discussion