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

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

ただいまの
回答率

91.25%

  • JavaScript

    11798questions

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

  • Python 3.x

    2775questions

    Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

  • Ajax

    836questions

    Ajaxとは、Webブラウザ内で搭載されているJavaScriptのHTTP通信機能を使って非同期通信を利用し、インターフェイスの構築などを行う技術の総称です。XMLドキュメントを指定したURLから読み込み、画面描画やユーザの操作などと並行してサーバと非同期に通信するWebアプリケーションを実現することができます。

  • Flask

    86questions

    FlaskはPython用のマイクロフレームワークであり、Werkzeug・Jinja 2・good intentionsをベースにしています。

Ajax + Flaskでアップロードした画像をwebサーバー内に保存すると0バイトになってしまう

解決済

回答 2

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 113

KoukoMatsumoto

score 35

Flaskでウェブアプリケーションを作っております。
Ajaxでinput type="file"で選択した画像を含めたPOST送信をし、ファイルアップロードをさせる仕組みを作っておりますが、
webサーバー内に画像保存する際に、保存したファイルが0バイトの壊れたものになってしまいます。
jpg、pngなどいろいろ試してみましたがどれも壊れてしまいます。
何か、原因がわかる方はいらっしゃいますでしょうか?
ご教授願えますと幸いです。

環境:
Python 3.6.2 :: Anaconda, Inc.
Flask 0.12.1
Ubuntu16.04
Bootstrap4系

結果:
以下のフォームでpngをアップロードすると、/tmp/images以下にimage.pngが作成されるが0バイトで壊れている

省略
<form class='ajax_submit' method="post" action="/post" id="imageform" enctype="multipart/form-data">
    <input type="file" id="image" name="image" style="display: none" accept="image/*">
</form>
省略
<div id="exec">
   button 
</div>
from flask import Flask, render_template, request, send_from_directory

@app.route('/post', methods=['POST'])
def post():
    upload_file = request.files['image']
    upload_file.save(os.path.join('/tmp/images', 'image.png')
window.onload = function() {
    var fileInput = document.getElementById('image');

    fileInput.addEventListener('change', function(e) {
        var file = fileInput.files[0];
        var imageType = /image.*/;

        if (file.type.match(imageType) &&) {
            var reader = new FileReader();
            reader.readAsDataURL(file);    
        }
    });

    $('#exec').click(function() {
        var form = $("form#imageform");
        var formData = new FormData( $(form).get(0) );
        $.ajax({
            url: $(form).attr('action'),
            type: 'post',
            data: formData,
            processData: false,
            contentType: false,
            success: function(data) {
                $('#result').html(data);
              },
              error: function() {
                    alert("Error");
              }
          });
    });
}
  • 気になる質問をクリップする

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

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

    クリップを取り消します

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

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

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

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

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

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

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

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

    質問の評価を下げる

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

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

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

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

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

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

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

    詳細な説明はこちら

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

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

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

回答 2

check解決した方法

0

upload_file = request.files['image']
upload_file.seek(0, os.SEEK_END)
app.logger.info(upload_file.tell())
upload_file.seek(0, 0)
upload_file.save(os.path.join('/tmp/images', 'image.png')
とすることで画像が正しく保存できました。
全文を乗せていないせいでご迷惑おかけして大変申し訳ございません・・・

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

0

<input type="file" id="image-file" name="image" style="display: none" 

ファイルを非表示にしているのは何かあるのでしょうか?
選択しないとファイルは送れないと思いますが・・・

$(function(){
  $('#exec').click(function() {
    var form = $("form#imageform");
    var formData = new FormData( $(form).get(0) );
    $.ajax({
    url: $(form).attr('action'),
    type: 'post',
    data: formData,
    processData: false,
    contentType: false,
    }).done(function(data) {
      $('#result').html(data);
    }).fail(function(xhr,err) {
      console.log(err);
    });
  });
});
<form class='ajax_submit' method="post" action="/post" id="imageform" enctype="multipart/form-data">
<input type="file" id="image-file" name="image" accept="image/*">
</form>
<div id="exec">button</div>
<div id="result"></div>

 追記

状況がいまいちまだわからないのですが
formdataをつかってajaxでpostしてるんですからfilereaderを使う意義がありません
同じデータをダブルで送ることになりませんか?

$(function(){
  $('#exec').on('click',function() {
    var form = $("form#imageform");
    var formData = new FormData( $(form).get(0) );
    var file = $('#image').prop('files')[0];
    var reader = new FileReader();
    var reg=new RegExp("image.*");
    if(!file.type.match(reg)) return false;
    reader.onload=function(e){
      formData.append("userfile", new Blob([reader.result],{"type":file.type}),file.name );
      $.ajax({
      url: $(form).attr('action'),
      type: 'post',
      data: formData,
      processData: false,
      contentType: false,
      }).done(function(data) {
        $('#result').html(data);
      }).fail(function(xhr,err) {
        alert(err);
      });
    };
    reader.readAsArrayBuffer(file);
  });
});
<form class='ajax_submit' method="post" action="y.php" id="imageform" enctype="multipart/form-data">
    <input type="file" id="image" name="image" accept="image/*">
</form>
<div id="exec">button</div>
<div id="result"></div>

投稿

編集

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2017/12/21 10:06

    すみません、ここの処理のjsの記載がが漏れてました。ファイル選択部分のデフォルトのボタンは隠して、画像クリックでアップロードできるようにしています。
    あとでソースを修正します。

    キャンセル

  • 2017/12/21 12:14

    javascriptのソースコードを追加させていただきました。
    ちなみにですが、request.filesの部分には中身のあるデータが渡ってきております。(ファイル名などが取れているため)

    キャンセル

  • 2017/12/21 13:26

    追記しましたが今ひとつ状況がわかりません。
    formdataでsubmitするのにfilereaderは不要です

    キャンセル

  • 2017/12/22 09:17

    わかりにくくて申し訳ございません。
    filereaderのけんは調べて見ます。やりたいこととしては、
    ・デフォルトのinput type=fileのデザインのボタンではなく、画像やテキストのクリックでファイルを選びたい
    ・非同期処理でflaskに通信しアップロードさせたい
    といった内容になります。


    全文そのままコピーできないため、 ソースコードの差異が有るかもしれません。見直して見ます。
    flask側でゼロバイトで保存されてしまうのは、jsの書き方が原因でしょうか・・・?

    キャンセル

  • 2017/12/22 09:19

    とりあえず私の提示したソースは試されましたか?
    選択したファイルとおなじサイズのファイルが送られているとわかると思います

    キャンセル

  • 2017/12/22 16:07

    大変申し訳ございません、自己解決してしまいました。
    ここに載せていないソースで、ファイルのサイズをseekで調査していたのですが、そちらでファイルポインタを戻していないのが原因のようでした。
    ajaxに関しては問題がなかったようです。
    お手数おかけしてこのような解決で心底申し訳ございません。

    キャンセル

  • 2017/12/22 16:09

    upload_file = request.files['image']
    upload_file.seek(0, os.SEEK_END)
    app.logger.info(upload_file.tell())
    upload_file.save(os.path.join('/tmp/images', 'image.png')
    のような処理になっておりまして、こちらで0バイトになってしまっていたようです・・・
    大変恐縮です。

    キャンセル

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

ただいまの回答率

91.25%

関連した質問

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

  • JavaScript

    11798questions

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

  • Python 3.x

    2775questions

    Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

  • Ajax

    836questions

    Ajaxとは、Webブラウザ内で搭載されているJavaScriptのHTTP通信機能を使って非同期通信を利用し、インターフェイスの構築などを行う技術の総称です。XMLドキュメントを指定したURLから読み込み、画面描画やユーザの操作などと並行してサーバと非同期に通信するWebアプリケーションを実現することができます。

  • Flask

    86questions

    FlaskはPython用のマイクロフレームワークであり、Werkzeug・Jinja 2・good intentionsをベースにしています。