🎄teratailクリスマスプレゼントキャンペーン2024🎄』開催中!

\teratail特別グッズやAmazonギフトカード最大2,000円分が当たる!/

詳細はこちら
Flask

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

React.js

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

Q&A

解決済

1回答

1713閲覧

[Flask]画像アップローダーでアップロードした画像が表示されない

aiai8976

総合スコア112

Flask

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

React.js

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

1グッド

0クリップ

投稿2020/12/30 05:04

編集2020/12/30 09:12

前提・実現したいこと

以下の記事を参考に、画像アップローダーを作っています。
自分の場合はフロントをReactで実装しています。
画像をアップロードしてflaskのuploadsディレクトリに画像ファイルをsaveできることは確認しました。
しかし、いざ直接"http://localhost:5000/uploads/画像名"のようにアクセスすると真っ白のままで何も表示されません。ログをみてみると200とあるので成功しているという状況です。
pythonのコード自体はあってそうなので、もしかすると画像ファイルがダメだったりするのでしょうか。
わかる方がいましたら、コメントお願いします。

####参考
https://qiita.com/keimoriyama/items/7c935c91e95d857714fb

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

127.0.0.1 - - [30/Dec/2020 13:52:51] "GET /uploads/20201227_112133_65D9F95F-E5EA-4599-9A1D-5F0A81E63A45.png HTTP/1.1" 200 -

該当のソースコード

app

1from flask import Flask, request, make_response, send_from_directory 2import os 3from datetime import datetime 4import werkzeug 5 6app = Flask(__name__) 7 8# データサイズの上限:1MB 9app.config['MAX_CONTENT_LENGTH'] = 1 * 1024 * 1024 10UPLOAD_DIR = os.getenv('UPLOAD_DIR_PATH') # ./uploads 11 12 13@app.route('/upload_image', methods=['POST']) 14def upload_image(): 15 if 'file' in request.files['image']: 16 return make_response(jsonify({'result':'file is empty.'})) 17 file = request.files['image'] 18 fileName = file.filename 19 saveFileName = datetime.now().strftime('%Y%m%d_%H%M%S_') + werkzeug.utils.secure_filename(fileName) 20 file.save(os.path.join(UPLOAD_DIR, saveFileName)) 21 22 return make_response(jsonify({'access_url':'http://localhost:3001/uploads/' + saveFileName })) 23 24 25@app.errorhandler(werkzeug.exceptions.RequestEntityTooLarge) 26def handle_over_max_file_size(error): 27 return make_response(jsonify({'result':'file size is overed.'})) 28 29 30@app.route('/uploads/<filename>', methods=['GET']) 31def show_uploaded_file(filename): 32 print(os.getenv('UPLOAD_DIR_PATH')) 33 return send_from_directory(os.getenv('UPLOAD_DIR_PATH'), filename) 34 35 36if __name__ == "__main__": 37 app.run(debug=True) 38

APP

1import React, { useState } from "react"; 2import "./App.css"; 3import axios from "axios"; 4 5function App() { 6 const [imageFormData, setImageFormData] = useState(); 7 8 const handleSetImage = (e) => { 9 if (!e.target.files) return; 10 const image = e.target.files[0]; 11 setImageFormData(image); 12 }; 13 14 function handleSubmit() { 15 const params = new FormData(); 16 if (!imageFormData) return; 17 params.append("image", imageFormData); 18 19 axios.post(`/upload_image`, params, {headers: {'Content-Type': 'multipart/form-data' }}).then((res) => { 20 console.log(res); 21 }); 22 } 23 24 return ( 25 <div className="App"> 26 <header className="App-header"> 27 <form onSubmit={handleSubmit}> 28 <label> 29 Upload file: 30 <input 31 type="file" 32 name="file" 33 accept=".png,.jpg" 34 onChange={(e) => handleSetImage(e)} 35 /> 36 </label> 37 <br /> 38 <button type="submit">Submit</button> 39 </form> 40 </header> 41 </div> 42 ); 43} 44 45export default App; 46

###試したこと

//console.log(e.target.files[0]) File {name: "65D9F95F-E5EA-4599-9A1D-5F0A81E63A45.png", lastModified: 1603460608788, lastModifiedDate: Fri Oct 23 2020 22:43:28 GMT+0900 (日本標準時), webkitRelativePath: "", size: 312117, …} lastModified: 1603460608788 lastModifiedDate: Fri Oct 23 2020 22:43:28 GMT+0900 (日本標準時) {} name: "65D9F95F-E5EA-4599-9A1D-5F0A81E63A45.png" size: 312117 type: "image/png" webkitRelativePath: ""
jyansinkai👍を押しています

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

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

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

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

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

A_kirisaki

2020/12/30 06:58

アップロードできた画像をビューワーなどで直接除きに行くことは出来ますか?
aiai8976

2020/12/30 07:23

今、finderから直接開こうとしたのですが、空だと言われました。
A_kirisaki

2020/12/30 07:27

React のアップロード部分のコード見せてください
aiai8976

2020/12/30 07:55

追加しました。確認お願いします。
guest

回答1

0

ベストアンサー

axios.post の第 3 引数に {headers: {'Content-Type': 'multipart/form-data' }} を渡してあげてみてください。

追記

ドキュメントをよく読もう!

わたしがです!

Uploading Files — Flask Documentation (1.1.x)
解決法:

Python

1... 2def upload_image(): 3 if 'file' in request.files: # <--- ここ!!! 4 return make_response(jsonify({'result':'file is empty.'})) 5 file = request.files['image'] 6...

なぜ 'file' in request.files['image'] ではダメなのか

標準入出力を始めファイル、ネットワークなどは最後まで読み切ってからデータを処理するのでは遅いので読み込みながら処理をします。これをストリーミング処理といい、そのデータが湧いてくる部分自体をストリームと言います。ストリーミング処理はデータを全部残しておくとメモリを圧迫するので、必要な分を返したら捨ててしまいます。

それで Flask もデータを効率よく処理するために Werkzeugの ストリーム処理を行うクラスを使っています。そしてここにある Request というクラスがその処理を担っているんですが、アクセスできるデータは全部ストリームなんです。request.files['image'] を呼んだ瞬間ストリーミング処理がバッと走って、その結果を代入しないと次 request.files['image'] を見に行っても中身が空、というわけなんですね。

という挙動がちゃんとドキュメントに書いてありました!ごめんドキュメント!!
Dealing with Request Data — Werkzeug Documentation (1.0.x)

投稿2020/12/30 08:12

編集2020/12/30 11:37
A_kirisaki

総合スコア2853

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

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

aiai8976

2020/12/30 08:50

追加してみましたが、空のままでした、、
A_kirisaki

2020/12/30 09:04

console.log(e.target.files[0]) するとどうなりますか?
aiai8976

2020/12/30 09:12

追加したので、確認お願いします。
aiai8976

2021/01/03 03:51

めちゃくちゃ勉強になりました!ありがとうございました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.36%

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

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

質問する

関連した質問