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

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

ただいまの
回答率

89.52%

@app.route('/upload')に末尾の/を入れると画像が表示されない。

解決済

回答 2

投稿

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

ikidaore

score 0

前提・実現したいこと

python3.7.4 flask1.1.1 werkzeug0.16.0 を使用してブラウザからアップロードした画像を表示するシステムを作っています。

@app.route('/upload')だと結果ページにアップロードした画像が正しく
表示されますが、@app.route('/upload/')のように末尾にスラッシュを加えると
画像が表示されなくなります。

末尾のスラッシュを記載しても正しく画像が表示されるようにしたいです。

どなたか、ご存知の方、ご回答頂けると幸いです。

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

【正常時】
127.0.0.1 - - [30/Sep/2019 13:06:07] "GET /static/hoge.jpg HTTP/1.1" 200 -

【エラー時】
127.0.0.1 - - [30/Sep/2019 14:45:24] "GET /upload/static/hoge.jpg HTTP/1.1" 404 -

該当のソースコード

upload.html

<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8"/>
    </head>
    <body>
        <h1>画像をアップロード</h1>
        <form method="POST" action="/upload" enctype="multipart/form-data">
            <input placeholder="名前" name="name" type="text"/>
            <input name="image" type="file"/>
            <input value="送信" type="submit"/>
        </form>
    </body>
</html>

result.html

<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8"/>
    </head>
    <body>
        <h1>アップロードされた画像</h1>
        <h2>{{name}}</h2>
        <img src="static/hoge.jpg" style="max-width: 320px">
    </body>
</html>

error.html

<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8"/>
    </head>
    <body>
        <h1>不正なリクエストです</h1>
    </body>
</html>

app.py

from flask import Flask, request, render_template
from werkzeug.utils import secure_filename

app = Flask(__name__)

@app.route('/upload/', methods=['GET'])
def render_upload_form():
    return render_template('upload.html')

@app.route('/upload/',methods=['POST'])
def upload_file():
    if request.form['name'] and request.files['image']:
        f = request.files['image']
        f.save('static/hoge.jpg')
        return render_template('result.html',name=request.form['name'])
    else:
        return render_template('error.html')

試したこと

@app.route('/upload/')の末尾の/を削除したところ、正しく画像が表示されました。

補足情報(FW/ツールのバージョンなど)

Windows10 VScode を使用して開発しております。

フォルダ構成は以下の通りです。
/
┣ app.py

┣ templates/
┃     ┣ upload.html
┃     ┣ result.html
┃     ┗ error.html

┗ static/
・  ┗ hoge.jpg
    

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

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

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

    クリップを取り消します

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

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

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

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

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

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

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

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

    質問の評価を下げる

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

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

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

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

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

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

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

    詳細な説明はこちら

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

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

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

回答 2

+1

        <form method="POST" action="/upload" enctype="multipart/form-data">


        <form method="POST" action="/upload/" enctype="multipart/form-data">


では


すみません。

https://flask.palletsprojects.com/en/1.1.x/api/#url-route-registrations

If a rule ends with a slash and is requested without a slash by the user, the user is automatically redirected to the same page with a trailing slash attached.

が効いていないという主旨の質問でしたら、この回答は不適切ですね。


追記

@app.route('/upload',methods=['POST'])


と書いて/uploadにアクセスすると表示された時のURLは/uploadになります。

@app.route('/upload/',methods=['POST'])


と書いて/uploadにアクセスしても、/uploadというURLに該当する関数は登録されていません。
ですが/を追加すると合致する関数が登録されているなら、HTTPステータスコード308を返し、/upload/にリダイレクトします。
ブラウザは308を受け取って、改めて/upload/にアクセスします。それで処理が行われるので、ブラウザで表示された時そのURLは/upload/になってます。

result.htmlには

<img src="static/hoge.jpg" (略)


と書いてあるので、
前者の場合ブラウザはイメージとして/static/hoge.jpgにアクセスします。
後者の場合ブラウザはイメージとして/upload/static/hoge.jpgにアクセスします。(ページのURLが/upload/ですから)

投稿

編集

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2019/09/30 16:41

    quiqui様
    ご回答ありがとうございます。
    迅速に回答を付けて頂き、とても心強いです。

    英語があまり得意ではないので、このページの内容を私が勘違いしていたら申し訳ありません。
    @app.routeの末尾にスラッシュが有るか無いかと、ブラウザのURL入力時に末尾にスラッシュがあるかないかで404になるかどうかの関係については、ルーティングのルールを理解しているつもりです。

    質問の趣旨としては、

    1.末尾スラッシュ有と無しで、result.htmlに表示する画像ファイルのPathが変化するのはなぜなのか?
    (今回の場合は以下のように)
    @app.route('/upload/') → /upload/static/hoge.jpg ※404エラー
    @app.route('/upload')  → /static/hoge.jpg ※表示される

    2.末尾のスラッシュがついても正しく表示された時と同じファイルパスで画像を表示するためにどうしたら良いのか。

    です。

    もしご存知でしたら教えて頂ければ嬉しいです。

    キャンセル

  • 2019/09/30 18:56

    quiqui様

    補足のご回答ありがとうございます。
    そういう事だったのですね。

    実際に試してみて、動きを把握するようにします。

    ご丁寧にありがとうございました。

    キャンセル

check解決した方法

0

解決しました。

result.html の↓の部分を

<img src="static/hoge.jpg" style="max-width: 320px">


↓のように しっかりと相対パスで指定するように書き換えたところ

<img src="../static/hoge.jpg" style="max-width: 320px">


表示されるようになりました。

どうやら@app.routeにバックスラッシュが無い時は、「static/hoge.jpg」の様な指定でもファイルを見つけてくれるようですが、バックスラッシュが有る時は、app.pyの位置から相対パスをしっかり記載しないとダメなようです。

@app.route(/upload) → result.htmlに記載されたパス
             [static/hoge.jpg][../static/hoge.jpg]どちらでも表示される。

@app.route(/upload/)→ result.htmlに記載されたパス
             [../static/hoge.jpg]と記載しないと表示されなかった。

回答して下さったquiqui様、ありがとうございました。
お騒がせ致しました。

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

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

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