iframe无法加载PDF内容,请求路径返回404错误排查
问题描述
尝试在iframe中加载PDF文件,流程是后端调用获取文件名和路径,传递给前端作为iframe的src,但出现404错误:
Not Found
The requested URL was not found on the server. If you entered the URL manually please check your spelling and try again.
后端Flask代码:
@auth.route("/building/view-file") def view_file(): filename = request.args.get("file") building = request.args.get("building") document = Document.query.filter_by(name=filename).first() print(document.path) return render_template( "building/Building/view_file.html", document=document.path, building=building )
前端HTML代码:
<iframe src="{{ document }}"></iframe> <button class="tenant_card_buttons" hx-get="/auth/building-info-expanded" hx-vals='{"building":"{{building}}"}' hx-target="#modal">Back</button> <button class="tenant_card_buttons" onclick="closeModal()">Close</button>
服务器日志:
FILE_STORAGE/Matric_Certificate.pdf 127.0.0.1 - - [28/Apr/2024 17:23:33] "GET /auth/building/view-file? file=Certificate.pdf&building=1 HTTP/1.1" 200 - 127.0.0.1 - - [28/Apr/2024 17:23:33] "GET /auth/FILE_STORAGE/Matric_Certificate.pdf HTTP/1.1" 404 -
疑问:哪里操作有误?为何iframe的src会触发重复的数据库查询?
问题分析与解决
1. 404错误的根源及修复
从日志能明显看出问题:
- 后端打印的文件路径是
FILE_STORAGE/Matric_Certificate.pdf,但浏览器实际请求的路径是/auth/FILE_STORAGE/Matric_Certificate.pdf。 - 原因是你传给iframe的是相对路径,浏览器会自动基于当前页面的URL(
/auth/building/view-file)拼接,把文件路径变成了/auth下的子路径,而服务器上根本没有这个路径的文件。
有两种修复方式:
- 方式一:改用绝对路径:在后端返回文件路径时加上根目录前缀,比如把
document=document.path改成document="/" + document.path,这样iframe的src就会是/FILE_STORAGE/Matric_Certificate.pdf,浏览器会直接从服务器根目录查找文件。 - 方式二:注册静态文件路由:如果
FILE_STORAGE是专门存文件的目录,需要给Flask添加一个路由来处理该目录下的文件请求:
配置后,浏览器请求from flask import send_from_directory @auth.route('/FILE_STORAGE/<path:filename>') def serve_storage_file(filename): # 确保FILE_STORAGE的路径正确,比如和app.py处于同一目录 return send_from_directory('FILE_STORAGE', filename)/auth/FILE_STORAGE/Matric_Certificate.pdf时,Flask就能正确找到并返回文件。
2. 关于"重复数据库查询"的澄清
从提供的日志来看,并没有触发重复的数据库查询:
- 日志里第一次请求
/auth/building/view-file是触发数据库查询的请求,对应你后端的view_file函数; - 第二次请求是浏览器加载iframe的src时发起的静态文件请求,这个请求不会走到你的
view_file视图函数,自然也不会执行任何数据库查询。你应该是误解了两次请求的含义,第二次和数据库完全无关。
内容的提问来源于stack exchange,提问作者stuart-kieser
相关产品推荐
相关产品推荐

