Flutter应用从StableDiffusion拉取图片偶发失败,报Invalid image data
问题分析:Flutter应用调用StableDiffusion API后上传Firebase Storage时时而失效
我开发的Flutter应用调用StableDiffusion API生成图片,再将图片上传至Firebase Storage,但该功能时而正常时而失效。不确定是无法访问图片还是存储环节出问题,相关代码和异常信息如下:
相关代码
StableDiffusion请求类
import 'dart:convert'; import 'package:flutter_dotenv/flutter_dotenv.dart'; import 'package:http/http.dart' as http; class StableDiffusionApi { final _url = Uri.parse('https://stablediffusionapi.com/api/v3/text2img'); Future getAIImage(String prompt) async { try { final response = await http.post( _url, headers: {"Content-Type": "application\/json"}, body: jsonEncode({ "key": "XXXX", "prompt": prompt, "negative_prompt": "((out of frame)), ((extra fingers)), mutated hands, ((poorly drawn hands)), ((poorly drawn face)), (((mutation))), (((deformed))), (((tiling))), ((naked)), ((tile)), ((fleshpile)), ((ugly)), (((abstract))), blurry, ((bad anatomy)), ((bad proportions)), ((extra limbs)), cloned face, (((skinny))), glitchy, ((extra breasts)), ((double torso)), ((extra arms)), ((extra hands)), ((mangled fingers)), ((missing breasts)), (missing lips), ((ugly face)), ((fat)), ((extra legs)), anime", "width": "512", "height": "512", "samples": "1", "num_inference_steps": "20", "seed": null, "guidance_scale": 7.5, "safety_checker": "yes", "webhook": null, "track_id": null }), ); var data = jsonDecode(response.body); return {"error": null, "data": data}; } catch (e) { print('ERROR:: ${e.toString()}'); return {"data": null, "error": e.toString()}; } } }
Firebase存储类
import 'package:cloud_firestore/cloud_firestore.dart'; import 'package:firebase_auth/firebase_auth.dart'; import '../../constants/all_tables.dart'; import '../../constants/diary.dart'; import '../../models/cloud/diary.dart'; import 'package:firebase_storage/firebase_storage.dart'; import 'dart:io'; import 'package:http/http.dart' as http; import 'package:path/path.dart' as path; import 'auth.dart'; class StorageFirebaseCloudStorage { final _user = AuthHandler.getUser(); Future uploadImageFromUrl(String imageUrl, String folderName) async { print("imageUrl: ${imageUrl}"); try { final imageResponse = await http.get(Uri.parse(imageUrl)); final imageBytes = imageResponse.bodyBytes; final fileName = "${_user.uid}_${Timestamp.now().millisecondsSinceEpoch}.jpg"; final storageRef = FirebaseStorage.instance.ref().child(folderName).child(fileName); final uploadTask = storageRef.putData(imageBytes); await uploadTask.whenComplete(() => null); final imageUrlInStorage = await storageRef.getDownloadURL(); return imageUrlInStorage; } catch (e) { print('ERROR'); print('Error uploading image:\n ${e.toString()}'); return null; } } Future<void> deleteFile(String fileUrl) async { try { final storage = FirebaseStorage.instance; final ref = storage.refFromURL(fileUrl); await ref.delete(); print('File deleted successfully'); } catch (e) { print('Error deleting file: $e'); } } static final StorageFirebaseCloudStorage _shared = StorageFirebaseCloudStorage._sharedInstance(); StorageFirebaseCloudStorage._sharedInstance(); factory StorageFirebaseCloudStorage() => _shared; }
抛出的异常信息
════════ Exception caught by image resource service ════════════════════════════ The following _Exception was thrown resolving an image codec: Exception: Invalid image data When the exception was thrown, this was the stack #0 _futurize (dart:ui/painting.dart:6408:5) #1 ImageDescriptor.encoded (dart:ui/painting.dart:6265:12) #2 instantiateImageCodecFromBuffer (dart:ui/painting.dart:2150:60) #3 PaintingBinding.instantiateImageCodecFromBuffer binding.dart:153 #4 NetworkImage._loadAsync _network_image_io.dart:135 <asynchronous suspension>
问题原因
StableDiffusion API返回无效URL或错误数据:
代码未校验API返回结果的有效性。当API调用超时、额度不足、生成失败时,返回的data可能不包含有效图片链接,甚至是错误信息。直接使用这个无效URL去请求,得到的不是图片字节,上传到Firebase后自然无法解析为图片,触发Invalid image data异常。图片URL请求未校验状态码:
在uploadImageFromUrl中,调用http.get获取图片字节时,没有检查响应状态码。如果请求图片URL返回404、500等错误,bodyBytes会是错误页面的HTML内容而非图片数据,上传后无法被识别为有效图片。API生成延迟导致URL暂时不可用:
即使API返回了URL,也可能存在图片尚未生成完成的情况,此时访问URL会得到临时占位内容或错误数据,导致后续上传的是无效数据。
修复建议
- 在调用
uploadImageFromUrl前,先校验StableDiffusion API返回的data:检查是否包含有效图片URL(比如data['output']是否存在且为合法HTTP链接),同时检查API响应的状态码是否为200。 - 在
uploadImageFromUrl中添加状态码校验:if (imageResponse.statusCode != 200) { throw Exception('Failed to fetch image, status code: ${imageResponse.statusCode}'); } - 添加图片有效性校验:检查
imageBytes的文件头是否符合JPG/PNG格式(比如JPG的前两个字节是0xFF 0xD8),避免上传无效数据。 - 针对API延迟情况,添加重试机制,间隔几秒后重新请求图片URL,确保图片已生成完成。
内容的提问来源于stack exchange,提问作者user17281101
相关产品推荐
相关产品推荐

