質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
Next.js

Next.jsは、Reactを用いたサーバサイドレンダリングなどを行う軽量なフレームワークです。Zeit社が開発しており、nextコマンドでプロジェクトを作成することにより、開発環境整備が整った環境が即時に作成できます。

Node.js

Node.jsとはGoogleのV8 JavaScriptエンジンを使用しているサーバーサイドのイベント駆動型プログラムです。

TypeScript

TypeScriptは、マイクロソフトによって開発された フリーでオープンソースのプログラミング言語です。 TypeScriptは、JavaScriptの構文の拡張であるので、既存の JavaScriptのコードにわずかな修正を加えれば動作します。

React.js

Reactは、アプリケーションのインターフェースを構築するためのオープンソースJavaScriptライブラリです。

Q&A

解決済

2回答

1499閲覧

【Next.js】fetchで送信した画像がサーバー側で取得できない

dimyas

総合スコア24

Next.js

Next.jsは、Reactを用いたサーバサイドレンダリングなどを行う軽量なフレームワークです。Zeit社が開発しており、nextコマンドでプロジェクトを作成することにより、開発環境整備が整った環境が即時に作成できます。

Node.js

Node.jsとはGoogleのV8 JavaScriptエンジンを使用しているサーバーサイドのイベント駆動型プログラムです。

TypeScript

TypeScriptは、マイクロソフトによって開発された フリーでオープンソースのプログラミング言語です。 TypeScriptは、JavaScriptの構文の拡張であるので、既存の JavaScriptのコードにわずかな修正を加えれば動作します。

React.js

Reactは、アプリケーションのインターフェースを構築するためのオープンソースJavaScriptライブラリです。

0グッド

0クリップ

投稿2022/11/17 11:25

編集2022/11/18 03:16

前提

Next.js × TypeScriptで画像送信フォームを作っています。
画像を選択してプレビューを表示するところまでできたのですが、送信でうまくいかないです。

実現したいこと

  • 複数画像の送信
  • サーバー内で画像の保存

発生している問題

フロント側の送信部分(一部抜粋)

TypeScript:index.tsx

1const data: postData = { 2 name: inputNameRef.current?.value, // 投稿名 3 files: images, // 画像データ配列のstate 4}; 5 6const post = await fetch(`${window.location.href}api/upload`, { 7 method: "POST", 8 headers: { 9 "Content-Type": "application/json", 10 }, 11 body: JSON.stringify(data), 12});

サーバー側のPOST

TypeScript:upload.ts

1import type { NextApiRequest, NextApiResponse } from "next"; 2type Data = { 3 name: string; 4}; 5export default function handler( 6 req: NextApiRequest, 7 res: NextApiResponse<Data> 8) { 9 10 console.log(req.body); // ここでnameしか確認できない 11 12 res.status(200).json({ name: "!!!" }); 13} 14

req.bodyの出力結果が以下のようになる

TypeScript

1{ name: 'TEST', files: [ {}, {} ] }

画像を2枚選択して送信したのだが、filesの中身が空のオブジェクトになっている

試したこと

  • 画像のデータをuseRefで取得する
  • new FormDataを使う
    • なぜかreq.body内が文字化けした

追記

FormDataを使った場合

以下で送信はできた

TypeScript

1const formData = new FormData(); 2formData.append("name", name || ""); 3 4for await(const [i, v] of Object.entries(images)) { 5formData.append("files", v ); 6} 7 8 9const post = await fetch(`${window.location.href}api/upload`, { 10method: "POST", 11body: formData, 12}); 13 14console.log(await post.json()); 15

ただし、サーバー側でのconsole.log(req.body);の中身が以下のようになって解析できない…

// …省略 ������;�������|k����^}owa�<�+n�>��hM�n�նU ���t���ѿ���]G��_���������1���X�� A&�29똺�;�������{���?����q�'@fΣ��]\��3���5��.����~Z��uw?�v�ak���?n�����du�����]��3�h޺���|��f=6K�h/#���k���T���J��u�+{��:�}G������ ���'���뫋�g>eo���L��V��������Y$�r� W�WI��gi��_��_�^s� �?c�U�˕�w�H�w_F�e^���+��{�BW��GU�/嵉?s��&ߛms����[��'���������9'ߓ����Y�r�kN+��w��Kx-���:o��tK�-���ׄ�Y״u��G� �|��Y���Z��k���o���UO��g��O�῿[P����w�����!)?ܫ�槨��?���z���w�+�^y0ǽ�J�/����l������>c�:f��#�.-!K{���~�W��.�Mro��x��/�k����?��ڕ�����?��+i�3�!�x�J�;Ǹ�m��7ݮG·W���?ޭ������j��R����)���>#���'��I������Ѯ����h����&�d{��8�?1��i��.���+Q��o�jE4O�X$��7˾x��[����$����%���-wW'c���/���qQ�I��CY�����W�T�n} �-!��H����<��U� ��7�#O�u_�zԷ_��mU�O����i�K����ǎKO9.><ϙ���#�ҿ �I�%���<�c��������y���������������t{����[�G����o<���{�Ͽ�8�j�?����ڕ��� I�\��s�4K��70\F�G��gܯU���湣�I�[���ٷ���������c���Q?������=C�S������#yk�W��r;��[�n�^��e�=?�z�� �?�e|5�������rV�3>�}*84�{����߯�Ŧ���{gg�I�e��}5���d�&� &Lq���7]2��}68<+��c��vW��Z����ϸu������׫|Y�����O����.���� ------WebKitFormBoundarywYqLipnWjIwkPquM--

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

maisumakun

2022/11/17 11:55

「画像データ配列のstate」とありますが、どのようなデータ形式でしょうか?
dimyas

2022/11/17 12:29

コメントありがとうございます。 データ形式の説明は難しいのですが、以下のように宣言しました。 const [images, setImages] = useState<File[]>([]); setImagesをする時は引数に以下のようにデータを渡します。 setImages([...e.target.files]);
guest

回答2

0

自己解決

フロント側はFormDataを使う

TypeScript

1const formData = new FormData(); 2 3for await(const [i, v] of Object.entries(images)) { 4 formData.append(i , v); 5} 6formData.append("name", name || ""); 7 8 9const post = await fetch(`${window.location.href}api/upload`, { 10 method: "POST", 11 body: formData, 12}); 13

サーバー側はformidableを使う

TypeScript

1 2import type { NextApiRequest, NextApiResponse } from "next"; 3import formidable from "formidable"; 4 5export const config = { 6 api: { 7 bodyParser: false, 8 }, 9}; 10type Data = { 11 name: string; 12}; 13export default function handler( 14 req: NextApiRequest, 15 res: NextApiResponse<Data> 16) { 17 18 if (req.method !== "POST") return; 19 20 const form = new formidable.IncomingForm({ multiples: true , uploadDir: __dirname}); 21 22 form.parse(req, async function (err, fields, files) { 23 if (err) { 24 res.status(500).json({name: err}); 25 res.end(); 26 return; 27 } 28 29 // ここでinput[type="text"]の{name:値}が取得できる 30 console.log(fields); 31 32 for await(const [i, v] of Object.entries(files)) { 33 console.log(i); 34 // ここにファイルのデータが入っているがどうやってサーバー内に書き出すか分からない 35 console.log(v); 36 37 } 38 39 res.status(200).json({ name: "!!!" }); 40 }) 41}

投稿2022/11/19 05:32

dimyas

総合スコア24

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

new FormDataを使う なぜかreq.body内が文字化けした

文字化けして特に問題ありません。画像ファイルのデータは(SVGを除けば)文字列として人間が読むことは基本的にできません。

投稿2022/11/17 13:00

maisumakun

総合スコア145184

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

dimyas

2022/11/17 13:34

new FormDataを使わないと、フォームのテキストとファイルを一緒に送信できないということですか?
maisumakun

2022/11/17 22:11

ファイルをPOSTしたい場合は、FormDataを使うのが標準的なやり方です。どうしてもJSONに詰め込みたい場合は、自力でファイルのデータをJSONに入れられる形に変換する必要があります。
dimyas

2022/11/18 03:12 編集

ありがとうございます。 以下のようにFormDataを使用して送信すると、req.bodyの中身が文字化けした状態で届きました。 軽く調べた感じこれをまた別のモジュールを使って変換しないといけないようですね ``` const formData = new FormData(); formData.append("name", name || ""); for await(const [i, v] of Object.entries(images)) { formData.append("files", v ); } const post = await fetch(`${window.location.href}api/upload`, { method: "POST", body: formData, }); console.log(await post.json()); ```
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問