当我使用图像选择器从Galery中选择图像时,将使用Flutter和laravel Rest API发送图像上传

发布于 2025-02-03 17:16:35 字数 4571 浏览 1 评论 0原文

当我使用图像拾取器从图库中选择图像时,我想在使用REST API发送的图像时上传。我正在寻找如何做的,但我仍然不明白,我尝试了不同的方法,但总是会出现错误。因此,如果有人知道将图像作为多部分数据发送到API的最佳方法。我的目标是连接颤音是前端,而拉拉维尔(Laravel)是后端。 在此先感谢

import 'dart:async';
import 'dart:convert';
import 'dart:io';

import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;

import 'package:image_picker/image_picker.dart';
import 'package:myapp/utils/api.dart';
import 'package:path/path.dart';
import 'package:flutter/foundation.dart' show kIsWeb;



class AddProduct extends StatefulWidget {
const AddProduct({Key? key}) : super(key: key);

@override
State<AddProduct> createState() => _AddProductState();
}

class _AddProductState extends State<AddProduct> {
bool _isLoading = false;
File? _image;

final _picker = ImagePicker();
// Implementing the image picker
Future<void> _openImagePicker() async {
final XFile? pickedImage =
    await _picker.pickImage(source: ImageSource.gallery);
if (pickedImage != null) {
  setState(() {
    _image = File(pickedImage.path);
  });
}
}

@override
Widget build(BuildContext context) {

return Scaffold(
  body: Container(
    child: _isLoading ? const Center(child: CircularProgressIndicator()) : ListView(
      children: <Widget>[
        textSection(),
        imageProduct(),
        buttonSection(context) 

      ],
    ),
  ),
  appBar: AppBar(
      title: const Text('Add Product')
  ),      
);

}

Container buttonSection(BuildContext context) {
return Container(
  width: MediaQuery.of(context).size.width,
  height: 40.0,
  padding: const EdgeInsets.symmetric(horizontal: 15.0),
  margin: const EdgeInsets.only(top: 15.0),
  child: ElevatedButton(
    onPressed: () {
      setState(() {
        _isLoading = true;
      });          
      addProducts(context, File(_image!.path));
    },
    child: const Text("Create", style: TextStyle(color: Colors.white)),
  ),
);
}

final TextEditingController _productName = TextEditingController();
final TextEditingController _description = TextEditingController();
final TextEditingController _price = TextEditingController();

Container textSection() {
return Container(
  padding: const EdgeInsets.symmetric(horizontal: 15.0, vertical: 20.0),
  child: Column(
    children: <Widget>[
      TextFormField(
        controller: _productName,
        cursorColor: Colors.black,

        style: const TextStyle(color: Colors.black),
        decoration: const InputDecoration(
          hintText: "Product name",
          border: OutlineInputBorder(),
          hintStyle: TextStyle(color: Colors.black54),
        ),
      ),
      TextFormField(
        controller: _description,
        cursorColor: Colors.black,
        maxLines: 10,

        style: const TextStyle(color: Colors.black),
        decoration: const InputDecoration(
          hintText: "Description",
          border: OutlineInputBorder(),
          hintStyle: TextStyle(color: Colors.black54),
        ),
      ),
      TextFormField(
        controller: _price,
        cursorColor: Colors.black,

        style: const TextStyle(color: Colors.black),
        decoration: const InputDecoration(
          hintText: "Price",
          border: OutlineInputBorder(),
          hintStyle: TextStyle(color: Colors.black54),
        ),
      ), 
    ] 
  ),      
);
}

Widget imageProduct() {
return Center(
  child: Stack(children: <Widget>[
    SizedBox(
      width: 100,
      height: 100,
      child: _image != null ? (kIsWeb)
                ? Image.network(_image!.path,  fit: BoxFit.cover)
                : Image.file(_image!, fit: BoxFit.cover) : const Text('Please select an image'),
    ),        
    Positioned(
      bottom: 20.0,
      right: 20.0,
      child: InkWell(
        onTap: () {
          _openImagePicker();              
        },
        child: const Icon(
          Icons.camera_alt,
          color: Colors.teal,
          size: 28.0,
        ),
      ),
    ),
  ]),
);
}

Future addProducts(BuildContext context, File imageFile) async {

var token = 'abc';
 var request = http.MultipartRequest(
   'POST',
   Uri.parse(Api.baseUrl + 'product/new'),
);

Map<String, String> headers = {
  "Accept": "application/json",
  "Authorization": "Bearer " + token
};   
 request.files.add(await http.MultipartFile.fromPath('image', imageFile.path));
 request.headers.addAll(headers); 
 request.fields['product_name'] = _productName.text;
 request.fields['description'] = _description.text;
 request.fields['price'] = _price.text;
 
 var response = await request.send();
} 

}

I want to make a product image upload when I select image from gallery using image picker it will send using REST API. I'm looking up how to do so and I still don't get it, I tried different methods but always getting an errors occur. So if anyone knows whats best way to send image as multipart data to API. My goal is to connect flutter is frontend and laravel is backend.
Thanks in advance

Flutter:

import 'dart:async';
import 'dart:convert';
import 'dart:io';

import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;

import 'package:image_picker/image_picker.dart';
import 'package:myapp/utils/api.dart';
import 'package:path/path.dart';
import 'package:flutter/foundation.dart' show kIsWeb;



class AddProduct extends StatefulWidget {
const AddProduct({Key? key}) : super(key: key);

@override
State<AddProduct> createState() => _AddProductState();
}

class _AddProductState extends State<AddProduct> {
bool _isLoading = false;
File? _image;

final _picker = ImagePicker();
// Implementing the image picker
Future<void> _openImagePicker() async {
final XFile? pickedImage =
    await _picker.pickImage(source: ImageSource.gallery);
if (pickedImage != null) {
  setState(() {
    _image = File(pickedImage.path);
  });
}
}

@override
Widget build(BuildContext context) {

return Scaffold(
  body: Container(
    child: _isLoading ? const Center(child: CircularProgressIndicator()) : ListView(
      children: <Widget>[
        textSection(),
        imageProduct(),
        buttonSection(context) 

      ],
    ),
  ),
  appBar: AppBar(
      title: const Text('Add Product')
  ),      
);

}

Container buttonSection(BuildContext context) {
return Container(
  width: MediaQuery.of(context).size.width,
  height: 40.0,
  padding: const EdgeInsets.symmetric(horizontal: 15.0),
  margin: const EdgeInsets.only(top: 15.0),
  child: ElevatedButton(
    onPressed: () {
      setState(() {
        _isLoading = true;
      });          
      addProducts(context, File(_image!.path));
    },
    child: const Text("Create", style: TextStyle(color: Colors.white)),
  ),
);
}

final TextEditingController _productName = TextEditingController();
final TextEditingController _description = TextEditingController();
final TextEditingController _price = TextEditingController();

Container textSection() {
return Container(
  padding: const EdgeInsets.symmetric(horizontal: 15.0, vertical: 20.0),
  child: Column(
    children: <Widget>[
      TextFormField(
        controller: _productName,
        cursorColor: Colors.black,

        style: const TextStyle(color: Colors.black),
        decoration: const InputDecoration(
          hintText: "Product name",
          border: OutlineInputBorder(),
          hintStyle: TextStyle(color: Colors.black54),
        ),
      ),
      TextFormField(
        controller: _description,
        cursorColor: Colors.black,
        maxLines: 10,

        style: const TextStyle(color: Colors.black),
        decoration: const InputDecoration(
          hintText: "Description",
          border: OutlineInputBorder(),
          hintStyle: TextStyle(color: Colors.black54),
        ),
      ),
      TextFormField(
        controller: _price,
        cursorColor: Colors.black,

        style: const TextStyle(color: Colors.black),
        decoration: const InputDecoration(
          hintText: "Price",
          border: OutlineInputBorder(),
          hintStyle: TextStyle(color: Colors.black54),
        ),
      ), 
    ] 
  ),      
);
}

Widget imageProduct() {
return Center(
  child: Stack(children: <Widget>[
    SizedBox(
      width: 100,
      height: 100,
      child: _image != null ? (kIsWeb)
                ? Image.network(_image!.path,  fit: BoxFit.cover)
                : Image.file(_image!, fit: BoxFit.cover) : const Text('Please select an image'),
    ),        
    Positioned(
      bottom: 20.0,
      right: 20.0,
      child: InkWell(
        onTap: () {
          _openImagePicker();              
        },
        child: const Icon(
          Icons.camera_alt,
          color: Colors.teal,
          size: 28.0,
        ),
      ),
    ),
  ]),
);
}

Future addProducts(BuildContext context, File imageFile) async {

var token = 'abc';
 var request = http.MultipartRequest(
   'POST',
   Uri.parse(Api.baseUrl + 'product/new'),
);

Map<String, String> headers = {
  "Accept": "application/json",
  "Authorization": "Bearer " + token
};   
 request.files.add(await http.MultipartFile.fromPath('image', imageFile.path));
 request.headers.addAll(headers); 
 request.fields['product_name'] = _productName.text;
 request.fields['description'] = _description.text;
 request.fields['price'] = _price.text;
 
 var response = await request.send();
} 

}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

谷夏 2025-02-10 17:16:35

我将图像转换为base64,在JSON中将base64发送到API。
在API中,A将base64转换为图像。

在颤音中:

Future<String?> convertImgToBase64() async {
    try {
      File img = File(_imageFile!.path);
      final splitted = _imageFile!.path.split('.');
      final ext = splitted.last;
      final response = await img.readAsBytes();
      return "data:image/$ext;base64,${base64Encode(response)}";
    } catch (e) {
      //print(e.toString());
      return null;
    }
  }

在拉拉维尔:

public function convertImage(Request $request, $id) {
        if($request->has('avatar')) {
            $data = $request->avatar;
            if (preg_match('/^data:image\/(\w+);base64,/', $data, $type)) {
                $data = substr($data, strpos($data, ',') + 1);
                $type = strtolower($type[1]);
                $name = "avatar_{$id}.{$type}" ;
                if (!in_array($type, [ 'jpg', 'jpeg', 'png' ])) {
                    throw new \Exception('Invalid image type');
                }
                $data = str_replace( ' ', '+', $data );
                $data = base64_decode($data);
                if ($data === false) {
                    throw new \Exception('Base64_decode failed');
                }
            } else {
                throw new \Exception('Did not match data URI with image data');
            }
            Storage::disk('local')->put("gallery/avatars/{$name}", $data);
            return $name;
            /*/if (file_put_contents($destination_path.$name, $data) != false) {
                return $name;
            } else {
                throw new \Exception('Unable to save image');
            }*/

        }
    }
}

I convert image to base64, I send base64 in the json to the API.
In the API a convert base64 to image.

In flutter :

Future<String?> convertImgToBase64() async {
    try {
      File img = File(_imageFile!.path);
      final splitted = _imageFile!.path.split('.');
      final ext = splitted.last;
      final response = await img.readAsBytes();
      return "data:image/$ext;base64,${base64Encode(response)}";
    } catch (e) {
      //print(e.toString());
      return null;
    }
  }

In laravel :

public function convertImage(Request $request, $id) {
        if($request->has('avatar')) {
            $data = $request->avatar;
            if (preg_match('/^data:image\/(\w+);base64,/', $data, $type)) {
                $data = substr($data, strpos($data, ',') + 1);
                $type = strtolower($type[1]);
                $name = "avatar_{$id}.{$type}" ;
                if (!in_array($type, [ 'jpg', 'jpeg', 'png' ])) {
                    throw new \Exception('Invalid image type');
                }
                $data = str_replace( ' ', '+', $data );
                $data = base64_decode($data);
                if ($data === false) {
                    throw new \Exception('Base64_decode failed');
                }
            } else {
                throw new \Exception('Did not match data URI with image data');
            }
            Storage::disk('local')->put("gallery/avatars/{$name}", $data);
            return $name;
            /*/if (file_put_contents($destination_path.$name, $data) != false) {
                return $name;
            } else {
                throw new \Exception('Unable to save image');
            }*/

        }
    }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文