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()