使用Flask上传文件至Google Drive时遇类型错误求助
Flask上传文件到Google Drive报错TypeError的解决方法
问题概述
命令行脚本可正常将文件上传至Google Drive,但通过Flask HTML表单上传时触发错误:
TypeError: expected str, bytes or os.PathLike object, not BufferedReader
报错原因
- 参数类型不匹配:PyDrive的
SetContentFile()方法要求接收文件路径字符串作为参数,代码中错误传递了open(path, "rb")返回的BufferedReader文件对象,导致类型校验失败。 - 变量引用错误:创建
gfile时误用self.folderId,但folderId是视图函数的局部变量,不存在self上下文,会触发NameError。
修复步骤
1. 修正SetContentFile参数
将传递文件对象改为直接传递文件路径字符串:
# 错误写法 gfile.SetContentFile(open(path, "rb")) # 正确写法 gfile.SetContentFile(path)
2. 修复变量引用错误
将self.folderId改为局部变量folderId:
# 错误写法 gfile = drive.CreateFile({'title': 'output.png', 'parents': [{'id': self.folderId}]}) # 正确写法 gfile = drive.CreateFile({'title': filename, 'parents': [{'id': folderId}]})
3. 可选优化:跳过本地文件保存
无需将上传文件保存到服务器本地,直接使用文件流上传,节省磁盘空间:
file = form.file.data filename = secure_filename(file.filename) gfile = drive.CreateFile({'title': filename, 'parents': [{'id': folderId}]}) gfile.content = file.stream # 直接使用上传的文件流 gfile.Upload()
完整修正后的main.py代码
from flask import Flask, render_template from flask_wtf import FlaskForm from wtforms import FileField, SubmitField from werkzeug.utils import secure_filename import os from wtforms.validators import InputRequired from pydrive.auth import GoogleAuth from pydrive.drive import GoogleDrive app = Flask(__name__) app.config['UPLOAD_FOLDER'] = 'static/files' app.config['SECRET_KEY'] = 'your-secret-key-here' # 必须配置,用于Flask-WTF表单验证 class UploadFileForm(FlaskForm): file = FileField("File", validators=[InputRequired()]) submit = SubmitField("Upload File") @app.route('/', methods=['GET', "POST"]) @app.route('/home', methods=['GET', "POST"]) def home(): form = UploadFileForm() gauth = GoogleAuth() drive = GoogleDrive(gauth) folderId = 'your-folder-id' # 替换为实际的Google Drive文件夹ID # 自动创建上传目录(若使用本地保存方案) os.makedirs(app.config['UPLOAD_FOLDER'], exist_ok=True) if form.validate_on_submit(): file = form.file.data filename = secure_filename(file.filename) # 方案1:保存到本地后上传 # save_path = os.path.join(os.path.abspath(os.path.dirname(__file__)), app.config['UPLOAD_FOLDER'], filename) # file.save(save_path) # gfile = drive.CreateFile({'title': filename, 'parents': [{'id': folderId}]}) # gfile.SetContentFile(save_path) # 方案2:直接用文件流上传(推荐) gfile = drive.CreateFile({'title': filename, 'parents': [{'id': folderId}]}) gfile.content = file.stream gfile.Upload() return '文件已成功上传至Google Drive!' return render_template('index.html', form=form) if __name__ == '__main__': app.run(debug=True)
额外注意事项
- 必须配置
SECRET_KEY,否则Flask-WTF的CSRF验证会失败。 - 替换代码中的
your-folder-id为实际的Google Drive目标文件夹ID。 - 若使用本地保存方案,
os.makedirs代码会自动创建缺失的上传目录。
内容的提问来源于stack exchange,提问作者emb
相关产品推荐
相关产品推荐

