Send image picker file to the backend - flutter

So I have this code that picks the image
Container(
child: ElevatedButton(
onPressed: () async {
result = await FilePicker.platform
.pickFiles(allowMultiple: true);
if (result == null) {
print("No file selected");
} else {
setState(() {
result?.files.forEach((element) {
attachmentController.text =
element.name;
statusController.text = "pending";
});
});
result?.files.forEach((element) {
print(element.name);
});
}
},
and I wanted to send this image to the backend of laravel but first, I have an attachment controller that saves the element.name but turns out it's just a name. May I please know how to save the image in the controller and if any links to show how to save that in the laravel backend please?
Thank you

If you are only picking images i will suggest you to use the image_picker package.
In your widget file :
File? image;
...
image= await ImagePicker.pickImage(source: ImageSource.gallery);
setState({});
You can use Image.file, widget factory method to show the image.
In your Api file :
import 'package:http/http.dart' as http;
import 'dart:convert';
...
var response = await http.post('example.com/api',
body: {
'image': base64Encode(await imageFile.readAsBytes()),
},
);
Depending on your Laravel you handle the request, decode it from base64 and save it to a folder.

Related

Flutter Firebase: storage on web with imagePicker

I have an implementation of imagePicker working with the mobile portion of my app, but i am currently trying to make it work on web too. Im getting an image with the following code:
ImagePicker _picker = ImagePicker();
final XFile? _image = await _picker.pickImage(
source: ImageSource.gallery,
imageQuality: 50,
);
if (_image == null) {
ScaffoldMessenger.of(context).showSnackBar(SnackBar(
content: Text('No image was selected.')));
}
if (_image != null) {
var f = await _image.readAsBytes();
StorageRepository()
.updateImage(user, _image, index);
}
Which leads to my confusion. My current storage method looks like this:
Future<void> uploadImageWeb(User user, XFile image, int? index) async {
try {
await storage
.ref('${user.id}/${image.name}')
.putFile(
File(image.path),
)
.then(
(p0) => FirestoreRepository().updateUserPictures(
user,
image.name,
index,
),
);
} catch (err) {
print(err);
}
}
Which obviously i cant use xfile, i have to use the Uint8List. But how do i read any data from that in a meaningful way to upload it to the storage bucket?
Thanks!

Send picture to server api with post request [FLUTTER]

I want to take picture, which should contain just a few letters, with my phone and then send it to a server where it will convert the picture to a text string.
My imported packages:
import 'dart:io';
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
import 'package:image_picker/image_picker.dart';
I currently have this camera function:
// Camera implementation
File? _image;
final ImagePicker _picker = ImagePicker();
Future getImage() async {
final image = await _picker.pickImage(source: ImageSource.camera);
setState(() {
_image = File(image!.path);
});
}
And I use it in this button:
// Camera button
ElevatedButton.icon(
onPressed: getImage,
icon: const Icon(Icons.camera_alt_rounded),
label: const Text('Scan'),
style: ButtonStyle(
backgroundColor: MaterialStateProperty.all(Colors.green[500]),
textStyle: MaterialStateProperty.all(const TextStyle(fontSize: 26)),
)
)
I have tested to just send some data to jsonplaceholder and it works, but I can't get understand how to implement it to a picture that should be sent to my server.
// Send Data to the Server (TEST VERSION)
postDataTest() async{
try{
var response = await http.post(Uri.parse("https://jsonplaceholder.typicode.com/posts"),
body: {
"id": 1.toString(),
"name": "Hax",
}
);
print(response.body);
} catch(e){
print(e);
}
}
TLDR. I want to take a picture and send it to a server.
Use multipart
Upload(File img) async {
var uri = Uri.parse(uploadURL);
var request = new http.MultipartRequest("POST", uri);
request.files.add( new http.MultipartFile.fromBytes("file", img.readAsBytesSync(), filename: "Photo.jpg", contentType: new MediaType("image", "jpg")));
var response = await request.send();
print(response.statusCode);
response.stream.transform(utf8.decoder).listen((value) {
print(value);
});
}
Picture to text for archive this you need to convert image into base64. Check this link
However, it's generally a bad idea to store large blobs of binary data in your database. you will end up wasting bandwidth transmitting data.it also decrease mobile app performance while you read large blob data. you don't need as well as unnecessary encoding and decoding.
You can send picture to server using multipart api request.
So you can archive mutipart request with api in various packages
https - dart documentation
Dio
You can also check multipartRequest on Stackoverflow.
I managed to solve it with this function:
// Upload camera photo to server
Future uploadImage() async {
final uri = Uri.parse("url to the server");
var request = http.MultipartRequest('POST', uri);
var takenPicture = await http.MultipartFile.fromPath("image", _image!.path);
request.files.add(takenPicture);
var response = await request.send();
if(response.statusCode == 200){
print('Image uploaded!');
} else{
print('Image not uploaded');
}
}
file.path is path of image u can use file picker or image picker in flutter
baseimage = "";
if(file.path != '') {
List<int> imageBytes = file.readAsBytesSync();
baseimage = base64Encode(imageBytes);
}
send image as a string and decode base64 in your server
laravel exemple using spatie media
if (isset($request->image)) {
$fiche_client->addMediaFromBase64($request->image)
->usingFileName(Str::random(10).'.png')
->toMediaCollection('magasin');
}

How to get Download URL from Firebase Storage in flutter

The Following Code is used to Upload any image from gallery/Camera to Firebase storage. I was successful in uploading the image to storage along with meta data. Now the problem is I am not able to get the download URL of the uploaded image. Tried a lot but didn't find any solution.
FirebaseStorage storage = FirebaseStorage.instance;
final picker = ImagePicker();
PickedFile pickedImage;
File imageFile;
Future<void> _upload(String inputSource) async {
try {
pickedImage = await picker.getImage(
source: inputSource == 'camera'
? ImageSource.camera
: ImageSource.gallery,
maxWidth: 1920);
final String fileName = path.basename(pickedImage.path);
imageFile = File(pickedImage.path);
try {
// Uploading the selected image with some custom meta data
await storage.ref(fileName).putFile(
imageFile,
SettableMetadata(
customMetadata: {
'uploaded_by': 'A bad guy',
'description': 'Some description...'
},
),
);
// Refresh the UI
setState(() {});
} on FirebaseException catch (error) {
print(error);
}
} catch (err) {
print(err);
}
}
Hope You're Doing Well …
You Can Try This Method To Get The URL Of The Image(Any File) From Firebase Storage To Firebase Store And Then You Can Retrieve Image .
class _UploadAdState extends State<UploadAdPage> {
final formKey = GlobalKey<FormState>();
File _myimage;
String imgUrl;
Future getImage1(File chosenimage) async {
PickedFile img =
await ImagePicker.platform.pickImage(source: ImageSource.gallery);
if (chosenimage == null) return null;
File selected = File(img.path);
setState(() {
_myimage = chosenimage;
});
}
// changing the firestore rules and deleteing if request.auth != null;
sendData() async {
// to upload the image to firebase storage
var storageimage = FirebaseStorage.instance.ref().child(_myimage.path);
UploadTask task1 = storageimage.putFile(_myimage);
// to get the url of the image from firebase storage
imgUrl1 = await (await task1).ref.getDownloadURL();
// you can save the url as a text in you firebase store collection now
}
}
I am using in my app this function. Pass image file and download with getDownloadUrl .
Future <String> _uploadphotofile(mFileImage) async {
final Reference storageReference = FirebaseStorage.instance.ref().child("products");
UploadTask uploadTask = storageReference.child("product_$productId.jpg").putFile(imgfile);
String url = await (await uploadTask).ref.getDownloadURL();
return url;
}

Flutter Image_Picker doesn't pick image from gallery and return to app

Here is a what's happening : I'm trying to upload an image from gallery to my app on iOS simulator. Image Picker opens the gallery but can't select an image and return to app. Here's my simple code:
File _image;
final picker = ImagePicker();
Future getImage() async {
final pickedFile = await picker.getImage(source: ImageSource.gallery);
setState(() {
if (pickedFile != null) {
_image = File(pickedFile.path);
} else {
print('No image selected.');
}
});
}
and my widget:
body: Center(
child: _image != null ? Image.file(_image) : Text('no Image'),
),
Thank you all in advance
For the iOS, as stated in the documentation, you'll need some config in the native side relating to permission:
Add the following keys to your Info.plist file, located in /ios/Runner/Info.plist:
NSPhotoLibraryUsageDescription - describe why your app needs permission for the photo library. This is called Privacy - Photo Library Usage Description in the visual editor.
NSCameraUsageDescription - describe why your app needs access to the camera. This is called Privacy - Camera Usage Description in the visual editor.
NSMicrophoneUsageDescription - describe why your app needs access to the microphone, if you intend to record videos. This is called Privacy - Microphone Usage Description in the visual editor.
Other than that, it should work perfectly fine with your code. The image should be fit within a Flexible like this, or maybe a SizedBox to avoid overflowing:
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:image_picker/image_picker.dart';
void main() {
runApp(MaterialApp(
home: SampleScreen(),
));
}
class SampleScreen extends StatefulWidget {
#override
_SampleScreenState createState() => _SampleScreenState();
}
class _SampleScreenState extends State<SampleScreen> {
File _image;
final picker = ImagePicker();
Future getImage() async {
final pickedFile = await picker.getImage(source: ImageSource.gallery);
setState(() {
if (pickedFile != null) {
_image = File(pickedFile.path);
} else {
print('No image selected.');
}
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
FlatButton(onPressed: () => getImage(), child: Text('Press me')),
Flexible(child: _image != null ? Image.file(_image) : Text('no Image')),
],
),
),
);
}
}
File _image;
String _image1 = "";
Future getImage() async {
final pickedFile = await picker.getImage(source: ImageSource.gallery);
setState(() {
if (pickedFile != null) {
_image1 = pickedFile.path;
_image = File(pickedFile.path);
print(json.encode(_image1));
print("file path...");
} else {
print('No image selected.');
}
});
}
In my case, I update my Image picker library from 0.6.3 to 0.8.4
hope this helps anyone.
You need to add the user permissions(key) and add the purpose(values) of these in info.plist file in iOS module.
Add the following keys to your Info.plist file, located in /ios/Runner/Info.plist:
NSPhotoLibraryUsageDescription - describe why your app needs permission for the photo library. This is called Privacy - Photo Library Usage Description in the visual editor.
NSCameraUsageDescription - describe why your app needs access to the camera. This is called Privacy - Camera Usage Description in the visual editor.
dependencies:
image_picker: ^0.8.4+4
import 'package:image_picker/image_picker.dart';
final picker = ImagePicker();
Future pickImage() async {
setState(() {
picselected1 = false;
});
ImagePicker picker = ImagePicker();
PickedFile pickedFile;
pickedFile = await picker.getImage(
source: ImageSource.gallery,
);
setState(() {
if (pickedFile != null) {
picselected1 = true;
// _images.add(File(pickedFile.path));
_image = File(pickedFile.path); // Use if you only need a single picture
} else {
print('No image selected.');
}
});
}
For everyone still dealing with this problem
Please not this in the image_picker documentary and make sure you tested it on a real device:
Starting with version 0.8.1 the iOS implementation uses PHPicker to
pick (multiple) images on iOS 14 or higher. As a result of
implementing PHPicker it becomes impossible to pick HEIC images on the
iOS simulator in iOS 14+. This is a known issue. Please test this on a
real device, or test with non-HEIC images until Apple solves this
issue

Flutter Dio : How to Upload Image?

I'm trying on Postman. And it works
I want upload some image to rest-api using Package DIO Package ,
I'm new for this package (i'm use this package just for CRUD operation) and i'm got problem when upload image operation.
i'm already reading documentation and nothing see for upload images. I'm try this code(ref on documentation) and got some error :
error:FileSystemException
message :"Cannot retrieve length of file"
OSError (OS Error: No such file or directory, errno = 2)
"File: '/storage/emulated/0/Android/data/com.example.mosque/files/Pictures/scaled_IMG_20190815_183541.jpg'"
Type (FileSystemException)
message:FileSystemException: Cannot retrieve length of file, path = 'File: '/storage/emulated/0/Android/data/com.example.mosque/files/Pictures/scaled_IMG_20190815_183541.jpg'' (OS Error: No such file or directory, errno = 2)
DioErrorType (DioErrorType.DEFAULT)
name:"DioErrorType.DEFAULT"
Api.dart
Future uploadImage({dynamic data,Options options}) async{
Response apiRespon = await dio.post('$baseURL/mahasiswa/upload/',data: data,options: options);
if(apiRespon.statusCode== 201){
return apiRespon.statusCode==201;
}else{
print('errr');
return null;
}
}
View.dart
void uploadImage() async {
FormData formData = FormData.from({
"name_image": _txtNameImage.text,
"image": UploadFileInfo(File("$_image"), "image.jpg")
});
bool upload =
await api.uploadImage(data: formData, options: CrudComponent.options);
upload ? print('success') : print('fail');
}
_image is type FILE
I hope who expert with this package can help me with this code and suggest me for upload images.
Thanks.
Full View.dart Code
import 'dart:io';
import 'package:dio/dio.dart';
import 'package:flutter/material.dart';
import 'package:image_picker/image_picker.dart';
import 'package:mosque/api/api_mosque.dart';
class UploadImage extends StatefulWidget {
#override
_UploadImageState createState() => _UploadImageState();
}
class _UploadImageState extends State<UploadImage> {
ApiHelper api = ApiHelper();
File _image;
TextEditingController _txtNameImage = TextEditingController();
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
leading: IconButton(
icon: Icon(Icons.arrow_left),
onPressed: () => Navigator.pop(context, false),
),
actions: <Widget>[
IconButton(
icon: Icon(Icons.file_upload),
onPressed: () {
uploadImage();
},
)
],
),
body: _formUpload(),
);
}
Widget _formUpload() {
return SingleChildScrollView(
scrollDirection: Axis.vertical,
child: Column(
children: <Widget>[
TextField(
controller: _txtNameImage,
keyboardType: TextInputType.text,
decoration: InputDecoration(hintText: "Nama Image"),
maxLength: 9,
textAlign: TextAlign.center,
),
SizedBox(
height: 50.0,
),
Container(
child: _image == null
? Text('No Images Selected')
: Image.file(_image),
),
SizedBox(
height: 50.0,
),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
RaisedButton(
child: Icon(Icons.camera),
onPressed: () => getImageCamera(),
),
SizedBox(
width: 50.0,
),
RaisedButton(
child: Icon(Icons.image),
onPressed: () => getImageGallery(),
)
],
)
],
),
);
}
void uploadImage() async {
FormData formData = FormData.from({
"name_image": _txtNameImage.text,
"image": UploadFileInfo(File("$_image"), "image.jpg")
});
bool upload =
await api.uploadImage(data: formData, options: CrudComponent.options);
upload ? print('success') : print('fail');
}
getImageGallery() async {
var imageFile = await ImagePicker.pickImage(source: ImageSource.gallery);
setState(() {
_image = imageFile;
});
}
getImageCamera() async {
var imageFile = await ImagePicker.pickImage(source: ImageSource.camera);
setState(() {
_image = imageFile;
});
}
}
In Dio latest version, UploadFileInfo method has been replaced by MultipartFile class. And here the way how to use to post image, video or any file:
Future<String> uploadImage(File file) async {
String fileName = file.path.split('/').last;
FormData formData = FormData.fromMap({
"file":
await MultipartFile.fromFile(file.path, filename:fileName),
});
response = await dio.post("/info", data: formData);
return response.data['id'];
}
Even this question is asked a while ago, I believe the main issue is the size of image especially with Laravel.Flutter Image Picker library offers some functionalities to reduce the size of Image, I solved it with bellow steps:
Create a method to get the Image, I am using Camera to Capture the photo
Future getImage() async {
File _image;
final picker = ImagePicker();
var _pickedFile = await picker.getImage(
source: ImageSource.camera,
imageQuality: 50, // <- Reduce Image quality
maxHeight: 500, // <- reduce the image size
maxWidth: 500);
_image = _pickedFile.path;
_upload(_image);
}
Create _upload method to upload the photo, I am using Dio package Dio Package
void _upload(File file) async {
String fileName = file.path.split('/').last;
FormData data = FormData.fromMap({
"file": await MultipartFile.fromFile(
file.path,
filename: fileName,
),
});
Dio dio = new Dio();
dio.post("http://192.168.43.225/api/media", data: data)
.then((response) => print(response))
.catchError((error) => print(error));
}
On the server side, I am using Laravel Laravel, I handle the request as follow
public function store(Request $request)
{
$file = $request->file('file');
$extension = $file->getClientOriginalExtension();
$fullFileName = time(). '.'. $extension;
$file->storeAs('uploads', $fullFileName, ['disk' => 'local']);
return 'uploaded Successfully';
}
In the latest version of Dio :
It should look like this.
String fileName = imageFile.path.split('/').last;
FormData formData = FormData.fromMap({
"image-param-name": await MultipartFile.fromFile(
imageFile.path,
filename: fileName,
contentType: new MediaType("image", "jpeg"), //important
),
});
If without this line.
contentType: new MediaType("image", "jpeg")
Maybe it will cause an error: DioError [DioErrorType.RESPONSE]: Http status error [400] Exception
And get MediaType in this package: http_parser
The following code uploads multiple image files from a dio client to a golang server.
dioclient.dart
FormData formData = FormData.fromMap({
"name": "wendux",
"age": 25,
"other" : "params",
});
for (File item in yourFileList)
formData.files.addAll([
MapEntry("image_files", await MultipartFile.fromFile(item.path)),
]);
Dio dio = new Dio()..options.baseUrl = "http://serverURL:port";
dio.post("/uploadFile", data: formData).then((response) {
print(response);
}).catchError((error) => print(error));
golangServer.go
package main
import (
"fmt"
"io"
"net/http"
"os"
)
func uploadFile(w http.ResponseWriter, r *http.Request) {
err := r.ParseMultipartForm(200000)
if err != nil {
fmt.Fprintln(w, err)
return
}
formdata := r.MultipartForm
files := formdata.File["image_files"]
for i, _ := range files {
file, err := files[i].Open()
defer file.Close()
if err != nil {
fmt.Fprintln(w, err)
return
}
out, err := os.Create("/path/to/dir/" + files[i].Filename)
defer out.Close()
if err != nil {
fmt.Fprintf(w, "Unable to create the file for writing. Check your write access privilege")
return
}
_, err = io.Copy(out, file)
if err != nil {
fmt.Fprintln(w, err)
return
}
fmt.Fprintf(w, "Files uploaded successfully : ")
fmt.Fprintf(w, files[i].Filename+"\n")
}
}
func startServer() {
http.HandleFunc("/uploadFile", uploadFile)
http.ListenAndServe(":9983", nil)
}
func main() {
fmt.Println("Server starts!")
startServer()
}
I have found a solution, where I am uploading file a specific directory which is generated different camera package which requires file path to save jpg file in the provided path.
and I was fetching file name with path and passing to
DIO package
which was giving file length issue, to I have implemented below steps to solve the issue
get File Name With Full Path from directory
create a File from the Path
File(directoryFilePathWithExtension);
and pass File.path to the dio package
MultipartFile.fromFile(
File(directoryFilePathWithExtension).path,
filename: DateTime.now().toIso8601String(),
)
Use UploadFileInfo.fromBytes if you're working with memory images (The error message above shows that your file is invalid and doesn't exist).
Hi there are many issue in file upload
try in android Api 21 because it did not have android permissions if api is working in android api 21 then it wil also work on above versions.
you might not able to get the file in above android version
you just need
FormData formData = FormData.fromMap({
"av_document": await MultipartFile.fromFile(_filePath,filename:
_fileName),
});
to upload any file or image to server and one more thing to note
_filePaths = await FilePicker.getMultiFilePath(type: _pickingType,
fileExtension: _extension);
_fileName = _filePath.split('/').last
by using this process u can upload file or image to server
I am using
dio: ^4.0.6 (for uploading)
flutter_native_image: ^0.0.6+1 (for reducing image size)
to reduce file size
File? compressedFile = profileImage.value == null
? null
: await FlutterNativeImage.compressImage(
profileImage.value?.path ?? '',
quality: 20,
percentage: 60);
dio formData map
var formData = dio.FormData.fromMap({
"name": input['name']!.text,
"profile_pic": await dio.MultipartFile.fromFile(compressedFile.path),
"birth_date": input['dob']!.text,})
request ->
response = await _dio.post(url, data: formData);