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

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

ただいまの
回答率

87.59%

フォームで取得した画像を縮小しajaxでアップロード

解決済

回答 2

投稿

  • 評価
  • クリップ 0
  • VIEW 1,099

score 5

前提・実現したいこと

<input type="file">で選択した画像をcanvasに縮小してプレビュー、それをjavascriptでblobデータで送信、phpでアップロードしたいです。

発生している問題・エラーメッセージ

ajaxにて縮小ファイル送信、受け取り側のphpでアップロードはできるのですが、元のinputで選択した縮小前の画像も一緒にアップロードされてしまいます。

該当のソースコード

<!--new.php-->
<form method="POST" enctype="multipart/form-data" action="done.php">
<input type="file" name="image" accept="image/*">
<input id="send" type="submit" value="登録">
</form>
//new.php内に記述
$('#send').click(function(){
if(!file || !blob) { //fileは選択されるファイル、blobは<canvas>に描画された縮小済みのblobデータ
return;
}

var fd = new FormData();
fd.append("image", blob);
for(item of fd) console.log(item);
$.ajax({
url: 'done.php',
type: 'POST',
dataType: 'json',
data: fd,
processData: false,
contentType: false
})

.done(function( data, textStatus, jqXHR ) {

})
.fail(function( jqXHR, textStatus, errorThrown ) {

});
//done.php
<?php
header("Content-type: text/html; charset=utf-8");
$tmpName = $_FILES['image']['tmp_name'];
$mime = $_FILES['image']['type'];

if($mime == 'image/jpeg' || $mime == 'image/pjpeg'){
$ext = '.jpg';
$image1 = imagecreatefromjpeg($tmpName);
} elseif($mime == 'image/png' || $mime == 'image/x-png'){
$ext = '.png';
$image1 = imagecreatefrompng($tmpName);
} elseif($mime == 'image/gif'){
$ext = '.gif';
$image1 = imagecreatefromgif($tmpName);
} else {
return false;
}
$filename = sha1(microtime() . $_SERVER['REMOTE_ADDR'] . $tmpName) . $ext;
$dir = 'image/'; 
$uploadfile = $dir . $filename;
if ($_FILES['image']){
$uploadfile = $dir . $filename;
move_uploaded_file($_FILES['image']['tmp_name'],$uploadfile);
} 

試したこと

Javascriptのfd.append("image", blob);のimageを別名に変えるとアップロードはできてましたがNotice: Undefined index: image in ~ とエラーがでました。

補足情報

for(item of fd) console.log(item);のchromeでのコンソール表示↓

(2) ["image", File]
0: "image"
1: File {name: "blob", lastModified: 1583374717041, lastModifiedDate: Thu Mar 05 2020 11:18:37 GMT+0900 (日本標準時), webkitRelativePath: "", size: 5591, …}
length: 2
proto: Array(0)

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

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

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

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

質問への追記・修正、ベストアンサー選択の依頼

  • yambejp

    2020/03/05 11:55

    > <input type="file">で選択した画像をcanvasに縮小してプレビュー、それをjavascriptでblobデータで送信、phpでアップロードしたいです。

    整理してください
    ・fileで選んだファイルをcanvasに流し込む?
    ・別にjpegやpngでプレビューすればいいのでは?
    ・blobデータで送信:ajaxないしfetchの処理?
    ・プレビューをなぜ送信するのでしょう?本データではまずい?
    ・blob送信はよいとして画像形式にコンバートしないとファイルにならないのでは?
    ・phpでアップロード:ちょっと表現が変。phpでうけて画像ファイルを保存するのですか?

    キャンセル

  • blacktm06

    2020/03/05 13:02

    初心者なものでちょっと理解できてない部分があると思います。

    ・fileで選んだファイルをcanvasに流し込む?
    ・別にjpegやpngでプレビューすればいいのでは?
    →プレビュー自体は構わないです。

    ・blobデータで送信:ajaxないしfetchの処理?
    →ajaxだと思います。

    ・プレビューをなぜ送信するのでしょう?本データではまずい?
    →容量が大きいので。リサイズして容量を減らしたデータを送りたいです。

    ・blob送信はよいとして画像形式にコンバートしないとファイルにならないのでは?
    アップロード自体は縮小されたものでされてました。

    ・phpでアップロード:ちょっと表現が変。phpでうけて画像ファイルを保存するのですか?
    →理解できていないこともあるので表現が間違っているかもしれません。。
    javascriptでdone.phpへ送信してdone.php内の move_uploaded_file で $_FILES を名前変えてアップロードするという理解でした。
    consolでみると元データと縮小データ2つ送られてるっぽいです。

    キャンセル

  • blacktm06

    2020/03/05 13:23

    ちなみに下記サイトを参考にしました。

    https://qiita.com/ma7ma7pipipi/items/1a1081b0dd71365a3e7e

    キャンセル

回答 2

checkベストアンサー

+3

formのsubmit止めてないようなのでdone.phpへの送信が2度起きてませんか?

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2020/03/05 19:01

    登録した後どうしたいか次第です。
    画面遷移したあとに何かDBやセッションなどPHP通さないと取れない情報が必要かとか。
    それも要件次第です。「完了しました」だけならJavaScriptで出せますし。

    キャンセル

  • 2020/03/06 13:20

    もともと考えていた内容としては、フォームにアイテム名などテキスト入力、画像を選択して登録ボタンを押すと完了画面(done.php)に遷移し$_POSTを受け取ってdone.php内のhtmlで登録内容の出力、画像はアップロード先のpathを返しimgタグで表示、DB登録といった内容にしたかったのです。画像がなかったらうまくいったのですが。。

    キャンセル

  • 2020/03/09 11:01

    シリアライズしてupload.phpに送信してmove_uploaded_fileでアップロード、その後done.phpのSELECT * FROM table ORDER BY id DESC LIMIT 1で引っ張ってくることにしました。
    今の理解度では精いっぱいです。。
    ありがとうございました!

    キャンセル

0

こんな感じで

<form enctype="multipart/form-data" method="post">
<input type="file" name="userfile" accept="image/*">
</form>
<canvas id="canvas"></canvas>

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2020/03/06 15:36 編集

    window.addEventListener('DOMContentLoaded', function(e){
    document.querySelector('[type=file]').addEventListener('change',function(e){
    var file = e.target.files[0];
    var type=file.type;
    var blob=new Blob([file],{type:type});
    var url = window.URL || window.webkitURL;
    var image = new Image();
    var ratio,width,height;
    image.src = url.createObjectURL(blob);
    image.onload=function(e){
    const THUMBNAIL_WIDTH = 100;
    const THUMBNAIL_HEIGHT = 100;
    if(image.width > image.height){
    ratio = image.height/image.width;
    width = THUMBNAIL_WIDTH;
    height = parseInt(THUMBNAIL_WIDTH * ratio);
    } else {
    ratio = image.width/image.height;
    width = parseInt(THUMBNAIL_HEIGHT * ratio);
    height = THUMBNAIL_HEIGHT;
    }
    var canvas = document.querySelector('#canvas');
    canvas.setAttribute('width', width);
    canvas.setAttribute('height', height);
    var ctx = canvas.getContext('2d');
    ctx.clearRect(0,0,width,height);
    ctx.drawImage(image,0,0,image.width,image.height,0,0,width,height);
    var type = 'image/jpeg';
    var dataurl = canvas.toDataURL(type);
    var bin = atob(dataurl.split(',')[1]);
    var buffer = new Uint8Array(bin.length);
    for (var i = 0; i < bin.length; i++) {
    buffer[i] = bin.charCodeAt(i);
    }
    var blob = new Blob([buffer.buffer], {type: type});

    const body=new FormData();
    body.append("myfile", blob,"test.jpg");
    const method="POST";
    fetch("done.php",{method,body}).then(res=>res.text()).then(console.log);
    }
    });
    });

    キャンセル

  • 2020/03/09 11:04

    わざわざコードを考えていただきありがとうございます!
    まだまだ私の理解度ではわからないコードだらけですのでひとつずつ調べて試していきたいと思います。

    キャンセル

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

  • ただいまの回答率 87.59%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る