Laravel转纯PHP:Flutter多图上传至PHP数据库技术问询
需求说明
我原本参考Laravel代码做开发,现在要改成纯PHP代码。前端用Flutter框架,已经靠image picker包实现了多图选择上传的功能,后端用PHP,需要完成把图片信息存入数据库的逻辑。
更新:前端多图上传的代码已经写好,如下:
class AddFlatGallery extends Stateful Widget { const AddFlatGallery({Key? key}) : super(key: key); @override State<AddFlatGallery> createState() => _AddFlatGalleryState(); } class _AddFlatGalleryState extends State<AddFlatGallery> { String flatname = ''; String buildingname = ''; String flatlocation = ''; Future CheckFlat() async { SharedPreferences preferencesaddflat = await SharedPreferences.getInstance(); setState(() { flatname = preferencesaddflat.getString('flatname') ?? "Not found"; buildingname = preferencesaddflat.getString('buildingname') ?? "Not found"; flatlocation = preferencesaddflat.getString('flatlocation') ?? "Not found"; }); } late List<Asset> images = []; Dio dio = Dio(); Widget buildGridView() { return GridView.count( crossAxisCount: 3, crossAxisSpacing: 7, children: List.generate(images.length, (index) { Asset asset = images[index]; return AssetThumb( asset: asset, width: 300, height: 300, ); })); } Future<void> loadAssets() async { List<Asset> resultList = []; try { resultList = await MultiImagePicker.pickImages( maxImages: 300, enableCamera: true, selectedAssets: images, cupertinoOptions: const CupertinoOptions(takePhotoIcon: "chat"), materialOptions: const MaterialOptions( actionBarColor: "#abcdef", actionBarTitle: "TenantPay", allViewTitle: "All Photos", useDetailsView: false, selectCircleStrokeColor: "#000000", )); } on Exception catch (e) { print(e.toString()); } if (!mounted) return; if (mounted) { setState(() { images = resultList; }); } } final Timer _timer = Timer.periodic(const Duration(seconds: 5), ((timer) {})); @override void dispose() { super.dispose(); _timer.cancel(); //cancel the timer here } _saveImage() async { if (images.isNotEmpty) { for (var i = 0; i < images.length; i++) { ByteData byteData = await images[i].getByteData(); List<int> imageData = byteData.buffer.asUint8List(); MultipartFile multipartFile = MultipartFile.fromBytes(imageData, filename: images[i].name, contentType: MediaType('image', 'jpg')); FormData formData = FormData.fromMap({ "image": multipartFile, "flat": flatname, "building": buildingname, "location": flatlocation, }); var response = await dio.post(ApiConstant.flatuploadurl, data: formData); if (response.statusCode == 200) { print(response.data); Fluttertoast.showToast( msg: "Images are added successfully", toastLength: Toast.LENGTH_SHORT, gravity: ToastGravity.CENTER, timeInSecForIosWeb: 3, backgroundColor: Colors.green, textColor: Colors.white, fontSize: 16.0); Navigator.of(context).pop(); Navigator.push( context, MaterialPageRoute( builder: (context) => const Home(), ), ); } } } } @override void initState() { super.initState(); CheckFlat(); } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( backgroundColor: const Color.fromARGB(255, 30, 64, 122), title: const Text( 'Upload Images', ), ), body: Padding( padding: const EdgeInsets.all(20.0), child: Column( children: [ FloatingActionButton( onPressed: () { loadAssets(); }, child: const Icon(Icons.add), ), Expanded(child: buildGridView()), Container( height: 60, padding: const EdgeInsets.fromLTRB(10, 10, 10, 0), child: CustomButton( text: 'Save', color: Colors.orange, onTap: () { _saveImage(); }, ), ), Container( height: 60, padding: const EdgeInsets.fromLTRB(10, 10, 10, 0), child: CustomButton( text: 'Continue without adding Images', color: Colors.blueAccent, onTap: () { Navigator.push( context, MaterialPageRoute( builder: (context) => const Home(), ), ); }, ), ), ], ), ), ); } }
纯PHP后端实现
1. 数据库表准备
先创建存储图片信息的表,执行以下SQL:
CREATE TABLE flat_gallery ( id INT AUTO_INCREMENT PRIMARY KEY, flat_name VARCHAR(255) NOT NULL, building_name VARCHAR(255) NOT NULL, location VARCHAR(255) NOT NULL, image_path VARCHAR(255) NOT NULL, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP );
2. 上传处理代码(upload_flat_images.php)
<?php // 数据库连接配置,根据自己的实际情况修改 $servername = "localhost"; $username = "your_db_username"; $password = "your_db_password"; $dbname = "your_db_name"; // 创建数据库连接 $conn = new mysqli($servername, $username, $password, $dbname); if ($conn->connect_error) { die(json_encode(["status" => "error", "message" => "数据库连接失败: " . $conn->connect_error])); } // 允许的图片类型 $allowed_types = ['image/jpeg', 'image/jpg']; // 最大文件大小(5MB) $max_size = 5 * 1024 * 1024; // 检查是否有文件上传 if (!isset($_FILES['image']) || $_FILES['image']['error'] !== UPLOAD_ERR_OK) { echo json_encode(["status" => "error", "message" => "图片上传失败"]); exit; } // 接收表单参数 $flat_name = $_POST['flat'] ?? ''; $building_name = $_POST['building'] ?? ''; $location = $_POST['location'] ?? ''; // 验证参数是否完整 if (empty($flat_name) || empty($building_name) || empty($location)) { echo json_encode(["status" => "error", "message" => "参数不完整"]); exit; } $file = $_FILES['image']; $file_type = $file['type']; $file_size = $file['size']; $file_name = basename($file['name']); // 验证文件类型 if (!in_array($file_type, $allowed_types)) { echo json_encode(["status" => "error", "message" => "只允许上传JPG/JPEG格式的图片"]); exit; } // 验证文件大小 if ($file_size > $max_size) { echo json_encode(["status" => "error", "message" => "图片大小不能超过5MB"]); exit; } // 生成唯一文件名,避免重名 $unique_name = uniqid() . '_' . $file_name; // 上传目录,确保这个目录存在且有写入权限,比如放在项目根目录下的uploads文件夹 $upload_dir = 'uploads/'; if (!is_dir($upload_dir)) { mkdir($upload_dir, 0777, true); } $file_path = $upload_dir . $unique_name; // 移动上传文件到目标目录 if (!move_uploaded_file($file['tmp_name'], $file_path)) { echo json_encode(["status" => "error", "message" => "图片保存失败"]); exit; } // 将图片信息存入数据库 $sql = "INSERT INTO flat_gallery (flat_name, building_name, location, image_path) VALUES (?, ?, ?, ?)"; $stmt = $conn->prepare($sql); $stmt->bind_param("ssss", $flat_name, $building_name, $location, $file_path); if ($stmt->execute()) { echo json_encode(["status" => "success", "message" => "图片上传成功"]); } else { // 如果数据库插入失败,删除已上传的图片 unlink($file_path); echo json_encode(["status" => "error", "message" => "数据库保存失败: " . $stmt->error]); } // 关闭连接 $stmt->close(); $conn->close(); ?>
注意事项
- 确保
uploads目录存在,并且给服务器赋予写入权限(生产环境可调整为更安全的权限配置) - 修改数据库连接参数为你自己的数据库信息
- 可根据需求调整允许的文件类型、最大文件大小
- 前端的
ApiConstant.flatuploadurl要指向这个PHP文件的访问地址
内容的提问来源于stack exchange,提问作者duaboola
相关产品推荐
相关产品推荐

