You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Flask+TensorFlow飞蝇识别应用:上传文件为空、图片无法显示求助

飞蝇钓假饵识别Flask应用问题排查

我是一名技术新手,同步学习Python、TensorFlow与Flask,开发了飞蝇钓假饵的TensorFlow图像识别模型,本地运行正常,但迁移到Flask Web应用后遇到两个问题:

  • 上传的图片文件被保存为0字节文件,文件名正确但内容为空;
  • 识别完成后无法正常显示上传的图片,仅显示通用“已上传图片”图标。

识别功能本身可正常运行,以下是我的代码:

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>

问题原因及修复方案

1. 0字节文件问题

问题出在recognize_fly函数:你先调用photo.read()把文件内容读取到photo_bytes,此时文件指针移到末尾,后续再调用photo.read()和photo.save()时,已经没有内容可读,导致保存的文件为0字节。

修复方式二选一:

  • 先保存文件,再从本地文件加载图像(推荐):
    修改recognize_fly函数:
@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"

    # 先保存文件到本地
    filename = os.path.join(app.config['UPLOAD_FOLDER'], photo.filename)
    photo.save(filename)
    
    # 从本地文件加载图像
    img = tf.keras.utils.load_img(filename, target_size=(img_height, img_width))
    img_array = tf.keras.utils.img_to_array(img)
    img_array = tf.expand_dims(img_array, 0)
    
    predictions = keras_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!)."
    
    print("Uploaded File:", photo.filename)
    return render_template('display.html', filename=photo.filename, recognition_results=recognition_results)
  • 读取文件后重置指针:
    在第一次photo.read()后添加photo.seek(0),把文件指针移回开头:
# Convert FileStorage to BytesIO
photo_bytes = BytesIO(photo.read())
photo.seek(0)  # 重置文件指针到开头

# ... 中间识别代码 ...

# 此时保存文件就能写入完整内容
photo.save(filename)

2. 图片无法显示问题

主要原因可能是uploads目录未创建,或者文件路径处理错误。

修复步骤:

  1. 应用初始化时自动创建uploads目录:
app = Flask(__name__)
UPLOAD_FOLDER = 'uploads'
app.config['UPLOAD_FOLDER'] = UPLOAD_FOLDER

# 自动创建uploads目录(不存在则创建)
os.makedirs(UPLOAD_FOLDER, exist_ok=True)
  1. 简化download_photo路由的路径处理:
@app.route('/download/<path:filename>')
def download_photo(filename):
    return send_from_directory(app.config['UPLOAD_FOLDER'], filename)

确认display.html中的图片路径{{ url_for('download_photo', filename=filename) }}正确,只要文件正常保存,就能正常显示。

内容的提问来源于stack exchange,提问作者Dave Franchino

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.13 21:30:56