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

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

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

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

Q&A

解決済

2回答

1203閲覧

Fetch を使って画像をサーバーに送信できません

takopo

総合スコア484

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

0グッド

0クリップ

投稿2020/09/15 08:14

質問させてください。
今 Javascript のFetchについて勉強しているのですが、こちらのサイトを参考にして、ユーザが canvas に描いた画像をサーバーに送信するというコードを試しました。

html

1<canvas class="canvas" width="100" height="80" style="border:1px solid"></canvas> 2<input class="btn" type="button" value="Submit">

Javascript

1const canvas = document.querySelector('.canvas'); 2const btn = document.querySelector('.btn'); 3 4canvas.onmousemove = function(e) { 5 let ctx = canvas.getContext('2d'); 6 ctx.lineTo(e.clientX, e.clientY); 7 ctx.stroke(); 8} 9 10function submit() { 11 canvas.toBlob(function(blob) { // HTMLCanvasElement.toBlob(callback) → キャンパスに描画したグラフィックをBlobに変換。返り値はなく、結果は第1引数に指定したコールバック関数に渡される 12 // console.log(blob); // => Blob { size: 608, type: "image/png" } 13 fetch('/image', { 14 method: 'POST', 15 body: blob 16 }) 17 .then(res => res.json()) // ←ここをコメントアウトするとエラーが出ませんでした 18 .then(result => alert(JSON.stringify(result, null, 2))) 19 }, 'image/png'); 20} 21 22btn.addEventListener('click', () => { 23 submit(); 24});

しかしローカルサーバーで実行したところ

Uncaught (in promise) SyntaxError: JSON.parse: unexpected end of data at line 1 column 1 of the JSON data

というエラーが出てしまい、画像がうまく送れません。
試しに.then(res => res.json())の部分をコメントアウトしてみるとエラーが出なかったので、Response オブジェクトから JSON を抽出するところに原因がありそうなのですが、解決方法が全く分からず困っております。
どなたか詳しい方がいらっしゃいましたらご教授いただけると助かります。
よろしくお願いいたします。

■ 開発環境
CentOS 7.6
vagrant 2.2.10
Firefox

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

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

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

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

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

guest

回答2

0

レスポンスされたheaders内のContent-Typeを確認してください。
型がapplication/jsonでなければ、JSONのパースは失敗しエラーになります。

参考にされたサイトに「レスポンス本文を取得するメソッド」の記述があります。
レスポンスされた型い対して適切なメソッドを利用する必要があります。
下記の方法でheadersの中身を確認してみてください。

Javascript

1res.headers.get('Content-Type')

投稿2020/09/16 08:50

Create_NAYU

総合スコア101

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

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

takopo

2020/09/16 09:54

ご回答ありがとうございます。 .then(res => res.headers.get('Content-Type')) .then(console.log) というふうに書いて確認してみましたところ 「text/html; charset=UTF-8」 と返ってきました。 application/jsonでないのが原因で、JSONのパースが失敗したことはわかったのですが、ここからどうすればいいのかがよくわかりません・・・解決方法をお教えただけるととても助かります。
Create_NAYU

2020/09/16 14:43 編集

一点確認です。 '/image'ではPOSTされたBlobデータを画像形式に変換してサーバ内に保存するという処理をしているのでしょうか? 解決策案として res.text() でテキスト化して内容で処理することもできると思いますが、オススメはできません。サーバー側を少しいじる必要があります。 処理をするサーバー側で headers に application/json を加えれば良いと思います。
takopo

2020/09/17 08:48

遅くなり申し訳ございません。 今回私は根本的な勘違いをしておりまして、「/image'」 を image ディレクトリのことだと思っておりました。 Create_NAYU様にご指摘いただいたことでサーバ内で処理をするファイルということが分かりました。 下記のように修正したところ、POST した画像のデータを取得することができました。 ``` fetch('/test.php', { method: 'POST', body: blob }) .then(res => res.text()) .then(result => console.log(result)) ``` ``` <?php $binarydata = file_get_contents('php://input'); $unpacked = unpack('C*', $binarydata); var_export($unpacked); ?> ``` お騒がせしてすみません。 この度は何度もご回答いただきありがとうございました! 無事解決でき助かりました。
guest

0

ベストアンサー

fetchで動きを確認しましたが
'/article/fetch-basics/post/image'送信後応答内容として
{"message":"Image saved, size:1790."}
が帰ってきていました。

JavaSclipt

1function submit() { 2 canvas.toBlob(function(blob) { 3 // HTMLCanvasElement.toBlob(callback) → キャンパスに描画したグラフィックをBlobに変換。返り値はなく、結果は第1引数に指定したコールバック関数に渡される 4 // console.log(blob); // => Blob { size: 608, type: "image/png" } 5 fetch('/image', { 6 method: 'POST', 7 body: blob 8 }) 9 .then(res => res.json()) // ←この時点で止めてみて下さい 10 .then(result => alert(JSON.stringify(result, null, 2))) 11 }, 'image/png'); 12}

ブラウザのデバッグ画面の「ネットワーク」で'/image'からどんな応答内容か届いているか
確認してみて下さい多分JSON形式ではない形式のようです。

投稿2020/09/16 08:39

kuma_kuma_

総合スコア2506

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

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

takopo

2020/09/16 10:11

ご回答ありがとうございます。 Firefox の「ネットワーク」の「応答」で確認しましたところ 「この要求には有効な応答データがありません」と出ていました。 参考サイトでタイプが「json」となっているところが「html」となっているので、ここを json にすればいいと思うのですが、どうすればよいのかが分かりません・・・
kuma_kuma_

2020/09/16 10:26

'/image'から応答が全く無いので何かJSON形式で値を返すようにして下さい。 例: {"message":"Test"} ちなみに質問者様から見た時のURL'/image'はどんな処理を行うのですか?
takopo

2020/09/17 08:47

遅くなり申し訳ございません。 今回私は 「fetch('/image'」 という部分を image ディレクトリのことだと勘違いしておりまして、そこに jpg や png が保存されるのだとばかり考えておりました。 /image は受け取ったバイナリデータを処理するファイルのことだったのですね。 kuma_kuma_様の「'/image'はどんな処理を行うのですか?」というご質問でやっと勘違いに気付きました。(お恥ずかしい…) 下記のように修正したところ、POST した画像のデータを取得することができました。 ``` fetch('/test.php', { method: 'POST', body: blob }) .then(res => res.text()) .then(result => console.log(result)) ``` ``` <?php $binarydata = file_get_contents('php://input'); $unpacked = unpack('C*', $binarydata); var_export($unpacked); ?> ``` この度は何度もご回答いただきありがとうございました! 無事解決でき助かりました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問