Flask应用程序意图下载文件,但下载的是一个零字节(空)文件。

huangapple go评论87阅读模式
英文:

Flask app intended to download a file is downloading a zero-byte (empty) file

问题

抱歉,你提供的内容是一段包含Python代码和描述的文本。以下是该文本的翻译:

"Newby here so please be patient and gentle. I am trying to learn a bit of tensorflow which is complicated by the fact that I suck at python so I'm trying to learn both at the same time. It's going about as well as you'd expect. As a fun exercise I thought I'd build a tensorflow image recognition model that can recognize fly fishing flies from a photo (my father-in-law gave me a zillion flies but I don't know what any of them are - hence the exercise).

So my simple tensorflow model is working well locally but I'm trying to migrate it to a web app (locally first - hopefully online eventually) using Flask (which I also don't know - get the pattern here).

So the objective is to present a web page that asks the user (me) to upload an image of the fly from a local file and then submit it to the engine to recognize it.

The image recognition is working (amazingly) but I would like to display the fly image and this is not working. I am just getting a generic "uploaded photo" icon.

In addition, the uploaded file is supposed to be stored in a local directory but the file that is being stored is empty (zero bytes) although the file name is correct.

Again, my knowledge of Python is simply terrible so I'm pretty sure I'm doing something dumb. Can anyone help me?

(also it's pretty clear I don't know how to insert code into a stack-overflow question!

Thank you kind hive!!!

Code follows for

FlyFinderWeb.py"

以上是文本的翻译部分,如果有任何需要进一步解释或帮助,欢迎提出。

英文:

Newby here so please be patient and gentle. I am trying to learn a bit of tensorflow which is complicated by the fact that I suck at python so I'm trying to learn both at the same time. It's going about as well as you'd expect. As a fun exercise I thought I'd build a tensorflow image recognition model that can recognize fly fishing flies from a photo (my father-in-law gave me a zillion flies but I don't know what any of them are - hence the exercise).

So my simple tensorflow model is working well locally but I'm trying to migrate it to a web app (locally first - hopefully online eventually) using Flask (which I also don't know - get the pattern here).

So the objective is to present a web page that asks the user (me) to upload an image of the fly from a local file and then submit it to the engine to recognize it.
Flask应用程序意图下载文件,但下载的是一个零字节(空)文件。

The image recognition is working (amazingly) but I would like to display the fly image and this is not working. I am just getting a generic "uploaded photo" icon.

Flask应用程序意图下载文件,但下载的是一个零字节(空)文件。

In addition, the uploaded file is supposed to be stored in a local directory but the file that is being stored is empty (zero bytes) although the file name is correct.

Flask应用程序意图下载文件,但下载的是一个零字节(空)文件。

Again, my knowledge of Python is simply terrible so I'm pretty sure I'm doing something dumb. Can anyone help me?

(also it's pretty clear I don't know how to insert code into a stack-overflow question!

Thank you kind hive!!!

Code follows for

FlyFinderWeb.py


from flask import Flask, render_template, request, redirect, url_for, send_from_directory
import numpy as np
import tensorflow as tf
import matplotlib.pyplot as plt
import os
from io import BytesIO

class_names = ['Pheasant Tail Nymph', 'Wooly Bugger', 'adams dry fly', 'elk hair caddis']
img_height = 180
img_width = 180

# Load the saved Keras model
keras_model = tf.keras.models.load_model('Fly_classifer_keras_model')

app = Flask(__name__)
UPLOAD_FOLDER = 'uploads'
app.config['UPLOAD_FOLDER'] = UPLOAD_FOLDER

@app.route('/', methods=['GET', 'POST'])
def upload_photo():
    if request.method == 'POST':
        if 'photo' not in request.files:
            return redirect(request.url)
        
        photo = request.files['photo']
        
        if photo.filename == '':
            return redirect(request.url)
        
        if photo:
            filename = os.path.join(app.config['UPLOAD_FOLDER'], photo.filename)
            photo.save(filename)
            return redirect(url_for('display_photo', filename=photo.filename))
    
    return render_template('upload.html')

@app.route('/download/<path:filename>')
def download_photo(filename):
    return send_from_directory(
        os.path.abspath(app.config['UPLOAD_FOLDER']), 
        filename
    )

@app.route('/display/<filename>')
def display_photo(filename):
    print(os.path.join(app.config['UPLOAD_FOLDER'], filename))  
    return render_template('display.html', filename=filename)


@app.route('/recognize', methods=['POST'])
def recognize_fly():
    if 'photo' not in request.files:
        return "No file part"
    
    photo = request.files['photo']
    
    if photo.filename == '':
        return "No selected file"

    
    # Convert FileStorage to BytesIO
    photo_bytes = BytesIO(photo.read())
    
    # Load the TensorFlow model
    model = keras_model
    
    img = tf.keras.utils.load_img(photo_bytes, target_size=(img_height, img_width))
    img_array = tf.keras.utils.img_to_array(img)
    img_array = tf.expand_dims(img_array, 0)
    
    predictions = model.predict(img_array)
    class_index = np.argmax(predictions[0])
    class_name = class_names[class_index]
    score = tf.nn.softmax(predictions[0])

   
    recognition_results = f"I think what you have here is a {class_name}. I'm {100*np.max(score):.2f}% sure of this (but I could be wrong!)."
    
    filename = os.path.join(app.config['UPLOAD_FOLDER'], photo.filename)
    print("Photo size:", len(photo.read()))  # Print the size of the photo content
    print("Uploaded File:", photo.filename)
    photo.save(filename)
    return render_template('display.html', filename=photo.filename, recognition_results=recognition_results)


app.run(debug=True, use_reloader=True) #automatically restart server if changes are detected  


if __name__ == '__main__':
    app.run(debug=True)

Display.html

<!doctype html>
<html>
<head>
    <title>Display Photo</title>
    <style>
        .image-container {
            text-align: center;
            margin-bottom: 20px; /* Added margin for spacing */
        }
        .image-container img {
            max-width: 100%;
            max-height: 400px;
        }
    </style>
</head>
<body>
    <h1>Uploaded Photo</h1>

    <div class="image-container">
        <img src="{{ url_for('download_photo', filename=filename) }}" alt="Uploaded Photo">
    </div>





    <h2>Fly Recognition Results:</h2>
    <p>{{ recognition_results }}</p>

    <p>Would you like to repeat another?</p>
    <a href="{{ url_for('upload_photo') }}">Upload Another</a>
</body>
</html>

upload.html

<!doctype html>
<html>
<head>
    <title>Upload and Display Photo</title>
</head>
<body>
    <h1>Upload a Photo Please 5.0</h1>

    <form method="POST" enctype="multipart/form-data" action="{{ url_for('recognize_fly') }}">
        <input type="file" name="photo" accept=".jpg, .jpeg, .png">
        <input type="submit" value="Submit image to my big Machine Learning brain to see if I can figure out what fly it is">
    </form>
</body>
</html>

See above... I tried and it created a zero byte file instead of downloading the entire file.

答案1

得分: 0

在处理程序函数recognize_fly中,看起来你多次调用了photo.read(),这会导致指针读取照片文件并将读取光标留在文件末尾(没有剩余可读的内容)。为了重置光标以供以后的read()调用,并允许图像上传/渲染,你应该在调用photo.read()后使用photo.seek(0)将读取光标返回到文件的开头,因为photo.save(filename)也在底层使用read()来保存文件。你可以在这里阅读更多详细信息。

@app.route('/recognize', methods=['POST'])
def recognize_fly():
    if 'photo' not in request.files:
        return "No file part"
    
    photo = request.files['photo']
    
    if photo.filename == '':
        return "No selected file"

    
    # Convert FileStorage to BytesIO
    photo_bytes = BytesIO(photo.read())
    photo.seek(0)
    
    # Load the TensorFlow model
    model = keras_model
    
    img = tf.keras.utils.load_img(photo_bytes, target_size=(img_height, img_width))
    img_array = tf.keras.utils.img_to_array(img)
    img_array = tf.expand_dims(img_array, 0)
    
    predictions = model.predict(img_array)
    class_index = np.argmax(predictions[0])
    class_name = class_names[class_index]
    score = tf.nn.softmax(predictions[0])

   
    recognition_results = f"I think what you have here is a {class_name}. I'm {100*np.max(score):.2f}% sure of this (but I could be wrong!)."
    
    filename = os.path.join(app.config['UPLOAD_FOLDER'], photo.filename)
    print("Photo size:", len(photo.read()))  # 打印照片内容的大小
    photo.seek(0)
    print("Uploaded File:", photo.filename)
    photo.save(filename)
    return render_template('display.html', filename=photo.filename, recognition_results=recognition_results)

英文:

Looks like you made multiple photo.read() calls in the handler function recognize_fly which will cause the pointer reads through the photo file and leaves the read cursor at the end of the file (with nothing left to read). To reset the cursor for later read() calls and allow the image to be uploaded/rendered, you should use photo.seek(0) after you called photo.read() to return the read cursor to the start of the file since the photo.save(filename) also use read() under the hood to save the file. You can read more details here

@app.route('/recognize', methods=['POST'])
def recognize_fly():
    if 'photo' not in request.files:
        return "No file part"
    
    photo = request.files['photo']
    
    if photo.filename == '':
        return "No selected file"

    
    # Convert FileStorage to BytesIO
    photo_bytes = BytesIO(photo.read())
    photo.seek(0)
    
    # Load the TensorFlow model
    model = keras_model
    
    img = tf.keras.utils.load_img(photo_bytes, target_size=(img_height, img_width))
    img_array = tf.keras.utils.img_to_array(img)
    img_array = tf.expand_dims(img_array, 0)
    
    predictions = model.predict(img_array)
    class_index = np.argmax(predictions[0])
    class_name = class_names[class_index]
    score = tf.nn.softmax(predictions[0])

   
    recognition_results = f"I think what you have here is a {class_name}. I'm {100*np.max(score):.2f}% sure of this (but I could be wrong!)."
    
    filename = os.path.join(app.config['UPLOAD_FOLDER'], photo.filename)
    print("Photo size:", len(photo.read()))  # Print the size of the photo content
    photo.seek(0)
    print("Uploaded File:", photo.filename)
    photo.save(filename)
    return render_template('display.html', filename=photo.filename, recognition_results=recognition_results)

huangapple
  • 本文由 发表于 2023年8月10日 11:21:01
  • 转载请务必保留本文链接:https://go.coder-hub.com/76872462.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定