Using DIO to upload images Data to my fastAPI. In my case, the data gets uploaded but only one image gets uploaded. And i recieve this Unhandled exception error in the debug console. Has anyone faced this issue recently? In the backend, i get the 201 created so the fastAPI backend works really well. Here is the upload method i am using:
_uploadImage() async {
for (int i = 0; i < imageFileList!.length; i ) {
var path = imageFileList![i].path;
_images!.add(await MultipartFile.fromFile(
path,
// filename: path.split('/').last,
// contentType: MediaType("image", "jpg")
));
var formData = FormData.fromMap(
{
// need to await for this async operation
"name": _pNameC.text,
"price": _pPriceC.text,
"description": _pDescriptionC.text,
"files": _images,
},
);
var response =
await DioClient.dio.post("http://10.0.2.2:8000/products/addProductFD",
data: formData,
options: Options(
contentType: 'multipart/form-data',
followRedirects: false,
validateStatus: (status) {
return status! < 500;
}));
debugPrint(response.toString());
}
}
The error i am getting:
I/flutter ( 9021): {"name":"ugu","price":25.0,"is_active":true,"imgs_url":["localhost:8000/static/product_images/30e2b2d6d58f8a23a5d6.jpg"],"id":11,"description":"kjhkaz","owner_id":null}
E/flutter ( 9021): [ERROR:flutter/lib/ui/ui_dart_state.cc(198)] Unhandled Exception: Bad state: Can't finalize a finalized MultipartFile.
E/flutter ( 9021): #0 MultipartFile.finalize
package:dio/src/multipart_file.dart:133
Please help!
CodePudding user response:
I was forcing the for loop to work not knowing that the DIO docs said that mapping the files to list is the correct way to upload multiple images. So i removed the for-loop and just mapped the images to list inside the form data and everyting is working fine now. Thanks to this post https://stackoverflow.com/a/64683825/12986987. My new upload code for Flutter(image_picker) to FastAPI is:
_uploadImage() async {
var formData = FormData.fromMap(
{
// need to await for this async operation
"name": _pNameC.text,
"price": _pPriceC.text,
"description": _pDescriptionC.text,
"files": imageFileList!
.map((item) => MultipartFile.fromFileSync(item.path,
filename: item.path.split('/').last))
.toList()
},
);
var response =
await DioClient.dio.post("http://10.0.2.2:8000/products/addProductFD",
data: formData,
options: Options(
contentType: 'multipart/form-data',
followRedirects: false,
validateStatus: (status) {
return status! < 500;
}));
debugPrint(_images!.join(","));
debugPrint(response.toString());
}
FastAPI Backend:
@router.post('/addProductFD', status_code=status.HTTP_201_CREATED)
async def create(
name: str = Form(...),
price: float = Form(...),
description: str = Form(...),
files: List[UploadFile] = File(...),
db: Session = Depends(get_db),
# current_user: Vendor = Depends(get_current_active_user)
):
fileList = []
for file in files:
try:
FILEPATH = "./static/product_images/"
pimage_name = FILEPATH imghex(file.filename)
contents = await file.read()
with open(pimage_name, 'wb') as f:
f.write(contents)
except Exception:
return {"message": "There was an error uploading the file(s)"}
finally:
await file.close()
fileList.append("localhost:8000" pimage_name[1:])
file_urls = ",".join(fileList)
new_item = Product(
name=name,
price=price,
description=description,
imgs_url=[file_urls],
# owner_id=current_user.id
)
db.add(new_item)
db.commit()
db.refresh(new_item)
return new_item
For the image_picker in flutter:
final ImagePicker imagePicker = ImagePicker();
List<XFile>? imageFileList = [];
void selectImages() async {
final List<XFile>? selectedImages = await imagePicker.pickMultiImage();
if (selectedImages!.isNotEmpty) {
imageFileList!.addAll(selectedImages);
}
setState(() {});
}
Thats all.