I am trying to receive more than one file per time using reactjs and flask api, but I get this error
data = file.read() AttributeError: 'str' object has no attribute 'read'
fontend code using reactjs
this.state = { file : [] } fileSelectHandler = (event) => { var totalfiles = event.target.files.length; for (var index=0; index < totalfiles; index++){ this.state.file.push(event.target.files[index]) } } async onFormSubmit (event) { event.preventDefault(); const formData = new FormData(); formData.append("file", this.state.file); await fetch(apiUrl+'photo/create' , { method: 'POST', body: formData }) }
backend code using flask
@app.route('/photo/create', methods=['POST']) def create_photo(): files = request.form.getlist("file") print(files) for file in files: data = file.read()
flask receiving the files as [‘[object File],[object File]’] .
I tried to find ways to read an object file but nothing worked can anyone help..
Advertisement
Answer
I don’t use React
but for me problem makes
formData.append("file", this.state.file);
because this.state.file
is list with one or many files and it needs for
-loop to add every file as separated object in Form
const formData = new FormData(); var totalfiles = this.state.file.length; for (var index=0; index < totalfiles; index++){ formData.append("file", this.state.file[index]); }
And now it sends all files in request.files
instead of one (useless) string '[object File],[object File]'
in request.form
Minimal working code
from flask import Flask, request, render_template_string app = Flask(__name__) @app.route('/', methods=['GET', 'POST']) def index(): return render_template_string(''' <!DOCTYPE html> <script> this.state = { file: [] } fileSelectHandler = (event) => { console.log("fileSelectHandler"); var totalfiles = event.target.files.length; for (var index=0; index < totalfiles; index++){ this.state.file.push(event.target.files[index]); } } async function onFormSubmit(event) { console.log("onFormSubmit"); event.preventDefault(); const formData = new FormData(); var totalfiles = this.state.file.length; for (var index=0; index < totalfiles; index++){ formData.append("file", this.state.file[index]); } // doesn't need `http://.../` if sends to the same server await fetch('/photo/create', { method: 'POST', body: formData, }); } </script> <input type="file" multiple onChange="fileSelectHandler(event);"> <button type="submit" onClick="onFormSubmit(event);">Submit</button> ''') @app.route('/photo/create', methods=['GET', 'POST']) def photo(): print('args :', request.args) print('form :', request.form) print('json :', request.json) print('files:', request.files) for file in request.files.getlist('file'): print(file.filename) #print(file.read()) return render_template_string(''' ''') if __name__ == '__main__': #app.debug = True app.run()