how to get the path from image_cropper in flutter? - laravel

I want to upload the cropped image in the server but I don't know how to get image path from the cropper. how do I get the path from the cropper. below is my code for cropping and for uploading the cropped image.
this is my code for cropping.
`void _cropImage(filePath) async {
CroppedFile? _croppedFile = await ImageCropper().cropImage(
sourcePath: filePath,
aspectRatioPresets: [
CropAspectRatioPreset.square,
CropAspectRatioPreset.ratio3x2,
CropAspectRatioPreset.original,
CropAspectRatioPreset.ratio4x3,
CropAspectRatioPreset.ratio16x9
],
uiSettings: [
AndroidUiSettings(
toolbarTitle: 'Cropper',
toolbarColor: Colors.deepOrange,
toolbarWidgetColor: Colors.white,
initAspectRatio: CropAspectRatioPreset.original,
lockAspectRatio: false),
IOSUiSettings(
title: 'Cropper',
),
],);
// compressFormat: ImageCompressFormat.jpg);
// cropImagePath.value = croppedFile!.path;
if (_croppedFile != null) {
setState(() {
imageFile = _croppedFile.path;
});
}
}
this is my code for uploading
`uploadImage() async {
var request = http.MultipartRequest(
'POST', Uri.parse('http://hsdgfddf/api/examples/add'));
request.files.add(await http.MultipartFile.fromPath(
'picture', croppedfile!.path));
http.StreamedResponse response = await request.send();
if (response.statusCode == 200) {
print(await response.stream.bytesToString());
}
else {
print(response.reasonPhrase);
}
}

You can get the image path when you set it once you received the modified cropped image is received.
Hope this helps.

try this
var request = http.MultipartRequest(
'POST',
Uri.parse("API"),
);
Map<String, String> headers = {"Content-type": "multipart/form-data"};
request.files.add(
http.MultipartFile(
'pic' //picture_index,
selectedImage.readAsBytes().asStream(),
selectedImage.lengthSync(),
filename: croppedImage.path.split('/').last,
),
);
request.headers.addAll(headers);
print("request: " + request.toString());
var res = await request.send();
http.Response response = await http.Response.fromStream(res);

Related

how to upload images in server using flutter and laravel api?

How to upload images in server using flutter with Laravel API? I tried using getx, its returning null. also I have image_picker and image_cropper package in my pubspec.yaml
Select Image from Gallery using File Picker
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:file_picker/file_picker.dart';
class ImageScreen extends StatefulWidget {
ImageScreen();
#override
State<ImageScreen> createState() => _ImageScreenState();
}
class _ImageScreenState extends State<ImageScreen> {
File file;
Future<File> uploadImage() async {
FilePickerResult result = await FilePicker.platform.pickFiles();
if (result != null) {
setState(() {
file = File(result.files.single.path);
});
print(result.files.single.path);
} else {
// User canceled the picker
}
return file;
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: GestureDetector(
onTap: () {
uploadImage();
},
child: Container(
color: Colors.green,
padding: EdgeInsets.all(5),
child: Text('Upload Image', style: TextStyle(fontSize: 16, color: Colors.white),)
),
),
);
}
}
Uploading Image to the server using http.multipartFile
static Future<dynamic> uploadImage({File file}) async {
try {
http.MultipartRequest request = new http.MultipartRequest("POST", _uri);
http.MultipartFile multipartFile = await http.MultipartFile.fromPath('file_name', file.path);
request.files.add(multipartFile);
var streamedResponse = await request.send();
var response = await http.Response.fromStream(streamedResponse);
if (response.statusCode == 200 ) {
return jsonDecode(response.body);
}
}
catch (e) {
return null;
}
}
final images = <File>[].obs;
Use this method for picking up images
Future pickImage(ImageSource source) async {
ImagePicker imagePicker = ImagePicker();
XFile pickedFile = await imagePicker.pickImage(source: source, imageQuality: 80);
File imageFile = File(pickedFile.path);
print(imageFile);
if (imageFile != null) {
images.add(imageFile);
} else {
Get.showSnackbar(GetSnackBar(message: "Please select an image file"));
}
}
Use this for uploading images to the server with your specific url.As I have used dio for uploading.You can use http as well.
Future<String> uploadImage(File file) async {
String fileName = file.path.split('/').last;
// you can edit it for your own convenience
var _queryParameters = {
'api_token': 'your token if required',
};
Uri _uri = 'Your base url'
var formData = FormData.fromMap({
"file": await MultipartFile.fromFile(file.path, filename: fileName),
});
var response = await dio.post(_uri, data: formData);
print(response.data);
if (response.data['data'] != false) {
return response.data['data'];
} else {
throw new Exception(response.data['message']);
}
}
This works for me, so maybe others might need it as well.
uploadImage(imageFile) async {
var stream = new http.ByteStream(
DelegatingStream.typed(imageFile.openRead()));
var length = await imageFile.length();
var uri = Uri.parse(
'http://192.168.5.196/ApiFileUploadTest/public/api/uploading-file-api');
var request = new http.MultipartRequest('POST', uri);
var multipartFile = new http.MultipartFile('file', stream, length,
filename: basename(imageFile.path));
request.files.add(multipartFile);
var response = await request.send();
print(response.statusCode);
response.stream.transform(utf8.decoder).listen((value) {
print(value);
});
}

Lambda Edge - The specified key does not exist

I am using lambda edge to handle image compression with Sharp. The code works for now, but when I tried to add a new function to parse query parameter to let the user define the quality of the compression, Lambda/Cloudfront starts giving me a notice that the key is not exist even though it does exist.
The path that was used as an example is:
/compress/480/uploads/1000491600869812260.jpg?quality=30
Error that shows up on the browser:
<Error>
<Code>NoSuchKey</Code>
<Message>The specified key does not exist.</Message>
<Key>compress/480/uploads/1000491600869812260.jpg</Key>
<RequestId>5KPMBD6RNETZCA3Z</RequestId>
<HostId>
brMd/eCi6uv9s3VIl4IRHg7FlIytNA8DkgPjGfGrej4SkUsMxuEm1YHGEEll5rydO24gecIOTtE=
</HostId>
</Error>
Errors log from cloudfront:
#Version: 1.0
#Fields: date time x-edge-location sc-bytes c-ip cs-method cs(Host) cs-uri-stem sc-status cs(Referer) cs(User-Agent) cs-uri-query cs(Cookie) x-edge-result-type x-edge-request-id x-host-header cs-protocol cs-bytes time-taken x-forwarded-for ssl-protocol ssl-cipher x-edge-response-result-type cs-protocol-version fle-status fle-encrypted-fields c-port time-to-first-byte x-edge-detailed-result-type sc-content-type sc-content-len sc-range-start sc-range-end
2021-06-09 06:06:43 ORD52-C3 689 182.253.36.23 GET d32xc09eirob59.cloudfront.net /compress/480/uploads/1000491600869812260.jpg 404 - Mozilla/5.0%20(Macintosh;%20Intel%20Mac%20OS%20X%2010_15_7)%20AppleWebKit/605.1.15%20(KHTML,%20like%20Gecko)%20Version/14.1.1%20Safari/605.1.15 quality=10 - Error FPFQE5Z-XuBeAK61KaJbNqDAbypyo3BhrH7xom7GZik--UgESIVQFw== d32xc09eirob59.cloudfront.net http 426 3.726 - - - Error HTTP/1.1 - - 54708 3.726 Error application/xml - - -
In the code below, if I comment the lines that call the function to parse the quality from query parameter (marked as "The problematic line" in the code), the code works again. But, from my point of view, there is nothing wrong with the code since it is a simple regex to fetch a value.
Is there any limitation or constraint in the AWS lambda that makes it behave like that? Is there anything that I can do to make it work?
P.S. I already tried to use URL and querystring library to parse the path, but it always shows me LambdaException error, hence why I try to parse it manually with regex
Problematic line/function:
const getQuality = (path) => {
const match = path.match(/quality=(\d+)/)
const quality = parseInt(match[1], 10)
return quality
}
const quality = getQuality(path)
Full code:
'use strict'
const AWS = require('aws-sdk')
const S3 = new AWS.S3({ signatureVersion: 'v4' })
const Sharp = require('sharp')
const BUCKET = 'some-bucket'
const QUALITY = 70
// Image types that can be handled by Sharp
const SUPPORTED_IMAGE_TYPES = ['jpg', 'jpeg', 'png', 'gif', 'webp', 'svg', 'tiff']
const JSON_CONTENT_HEADER = [{ key: 'Content-Type', value: 'application/json' }]
const WEBP_CONTENT_HEADER = [{ key: 'Content-Type', value: 'image/webp' }]
const getOriginalKey = (path) => {
const match = path.match(/\/(\d+)\/([A-Za-z0-9_\-]+)\/([A-Za-z0-9_\-]+)\.(\w+)\??/)
const imageWidth = parseInt(match[1], 10)
const prefix = match[2]
const imageName = match[3]
const imageFormat = match[4]
const originalKey = `${prefix}/${imageName}.${imageFormat}`
return { originalKey, imageWidth, imageFormat }
}
const getQuality = (path) => {
const match = path.match(/quality=(\d+)/)
const quality = parseInt(match[1], 10)
return quality
}
const responseUpdate = (
response,
status,
statusDescription,
body,
contentHeader,
bodyEncoding = undefined
) => {
response.status = status
response.statusDescription = statusDescription
response.body = body
response.headers['content-type'] = contentHeader
if (bodyEncoding) {
response.bodyEncoding = bodyEncoding
}
return response
}
exports.handler = async (event, context, callback) => {
let { request, response } = event.Records[0].cf
const { uri } = request
const headers = response.headers
console.log(JSON.stringify({ status_code: response.status, uri }))
// NOTE: Check whether the image is present or not
if (response.status == 404) {
const splittedUri = uri.split('compress')
if (splittedUri.length != 2) {
callback(null, response)
return
}
// NOTE: Parse the prefix, image name, imageWidth and format
const path = splittedUri[1] // Read the required path (/480/uploads/123.jpg)
const { originalKey, imageWidth, imageFormat } = getOriginalKey(path)
if (!SUPPORTED_IMAGE_TYPES.some((type) => type == imageFormat.toLowerCase())) {
response = responseUpdate(
response,
403,
'Forbidden',
'Unsupported image type',
JSON_CONTENT_HEADER
)
callback(null, response)
return
}
try {
// NOTE: Get original image from S3
const s3Object = await S3.getObject({ Bucket: BUCKET, Key: originalKey }).promise()
if (s3Object.ContentLength == 0) {
response = responseUpdate(
response,
404,
'Not Found',
'The image does not exist',
JSON_CONTENT_HEADER
)
callback(null, response)
return
}
// NOTE: Optimize the image
let sharpObject = await Sharp(s3Object.Body)
const metaData = await sharpObject.metadata()
if (imageWidth < metaData.width) {
sharpObject = await sharpObject.resize(imageWidth)
}
// >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
// NOTE: The problematic line
const quality = getQuality(path)
// <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
const compressedImageBuffer = await sharpObject.webp({ quality: QUALITY }).toBuffer()
const byteLength = Buffer.byteLength(compressedImageBuffer, 'base64')
if (byteLength == metaData.size) {
callback(null, response)
return
}
if (byteLength >= 1046528) {
response = responseUpdate(
response,
400,
'Invalid size',
'The size of compressed image is too big',
JSON_CONTENT_HEADER
)
callback(null, response)
return
}
// NOTE: Generate a binary response with an optimized image
response = responseUpdate(
response,
200,
'OK',
compressedImageBuffer.toString('base64'),
WEBP_CONTENT_HEADER,
'base64'
)
response.headers['cache-control'] = [{ key: 'cache-control', value: 'max-age=31536000' }]
} catch (err) {
console.error(err)
}
} else {
headers['content-type'] = WEBP_CONTENT_HEADER
}
return response
}

Convert Uint8List image data to ImageGallerySaver saveFile String

how can I convert the Uint8List imagedata of the Screenshot Package to save it with the ImageGallerySaver package saveFile command, which needs a string?
TextButton(
onPressed: () {
_imageFile = null;
screenshotController
.capture()
.then((Uint8List image) async {
//print("Capture Done");
setState(() {
_imageFile = image;
});
final result = await ImageGallerySaver.saveFile();
print("File Saved to Gallery");
}).catchError((onError) {
print(onError);
});
I found a solution:
TextButton(
onPressed: () {
_imageFile = null;
screenshotController
.capture()
.then((Uint8List image) async {
//print("Capture Done");
String dir =
(await getApplicationDocumentsDirectory()).path;
File file = File("$dir/" +
DateTime.now().millisecondsSinceEpoch.toString() +
".png");
await file.writeAsBytes(image);
setState(() {
_imageFile = image;
});
final result =
await ImageGallerySaver.saveFile(file.path);
print("File Saved to Gallery");
}).catchError((onError) {
print(onError);
});
},
child: Icon(Icons.change_history),
), // Thi

how to send react-native-audio-record recorded audio file to server?

I need to be record audio and upload audio to server and for the record audio i am using "react-native-audio-record" react native package.
When i am using file_get_contents($request->file('inputFile')) all time file_get_contents returning 500 internal server error to me in Laravel.
I tried form-data, blob object.
Here is my React Native code and everything what i used to solve this:
onStartRecord = async () => {
this.setState({ isPlaying: false })
let dirs = RNFetchBlob.fs.dirs
if (Platform.OS === 'android') {
try {
const granted = await PermissionsAndroid.request(
PermissionsAndroid.PERMISSIONS.WRITE_EXTERNAL_STORAGE,
{
title: 'Permissions for write access',
message: 'Give permission to your storage to write a file',
buttonPositive: 'ok',
},
);
if (granted === PermissionsAndroid.RESULTS.GRANTED) {
console.log('You can use the storage');
} else {
console.log('permission denied');
return;
}
} catch (err) {
console.warn(err);
return;
}
}
if (Platform.OS === 'android') {
try {
const granted = await PermissionsAndroid.request(
PermissionsAndroid.PERMISSIONS.RECORD_AUDIO,
{
title: 'Permissions for write access',
message: 'Give permission to your storage to write a file',
buttonPositive: 'ok',
},
);
if (granted === PermissionsAndroid.RESULTS.GRANTED) {
console.log('You can use the camera');
} else {
console.log('permission denied');
return;
}
} catch (err) {
console.warn(err);
return;
}
}
const path = Platform.select({
ios: 'hello.m4a',
//android: dirs.DocumentDir+'/hello.aac',
android: 'sdcard/hello.mp3',
});
const audioSet: AudioSet = {
// AudioEncoderAndroid: AudioEncoderAndroidType.AAC,
// AudioSourceAndroid: AudioSourceAndroidType.MIC,
// AVEncoderAudioQualityKeyIOS: AVEncoderAudioQualityIOSType.high,
// AVNumberOfChannelsKeyIOS: 2,
// AVFormatIDKeyIOS: AVEncodingOption.aac,
};
//console.log('audioSet', audioSet);
const uri = await this.audioRecorderPlayer.startRecorder(path);
console.log("URI => ",uri);
// RNFS.readFile(uri, 'base64')
// .then(res =>{
// console.log(res);
// });
// RNFetchBlob.fs.writeFile(path, base64Str, 'base64');
// RNFetchBlob.android.actionViewIntent(path, 'application/aac');
this.audioRecorderPlayer.addRecordBackListener((e: any) => {
//console.log("E ====>>>>>>>>>",e);
this.setState({
recordSecs: e.current_position,
recordTime: this.audioRecorderPlayer.mmssss(
Math.floor(e.current_position),
),
});
});
//alert(`uri: ${uri}`);
// var body = new FormData();
// //console.log("BODY",abc);
// body.append('file', uri);
//
// console.log("+++++++=========body=========++++++",body);
var body = new FormData();
//console.log("BODY",abc);
body.append('inputFile', {
name: 'sound.mp4',
type: 'audio/mp3',
uri: uri
});
console.log("+++++++=========body=========++++++",body);
// console.log("BODY",body);
// RNFS.readFile(uri, "base64").then(data => {
// // binary data
// console.log("+++++++=========URI=========++++++",data);
// });
// const formData = [];
// formData.push({
// name: "sound",
// filename: `sound.mp4`,
// data: RNFetchBlob.wrap(uri)
// });
const blob = await (await fetch(uri)).blob();
// const file = new File(this.state.recordTime, `me-at-thevoice${1}.mp3`, {
// type: blob.type,
// lastModified: Date.now()
// });
// console.log("Bolb data file",file);
var bodyData = new FormData();
//console.log("BODY",abc);
bodyData.append('inputFile', { blob });
//
// console.log("RNFetchBlob blob",blob);
// await new Promise(resolve => {
// var reader = new FileReader();
// reader.readAsDataURL(blob);
// reader.onloadend = () => {
// var base64data = reader.result;
// console.log("reader",reader);
// console.log("base64data =--->>>",base64data);
// // let pth = path
// // RNFetchBlob.fs.writeFile(pth, reader.result.substr(base64data.indexOf(',')+1), 'base64').then((res) => {
// // console.log("RNFetchBlob res",res);
// // blob.close()
// // resolve();
// // });
//
this.props.setLoader(true);
this.props.uploadAudio(bodyData).then(result => {
console.log("this.props.audioRecordingResponse |||||=====|||||",this.props.audioRecordingResponse);
if (this.props.audioRecordingResponse.success) {
this.handler('success','Success',this.props.audioRecordingResponse.message);
// this.refs["sign"].resetImage();
// this.setState({
// signatures: [],
// isDragged: false,
// signatureCount: 0
// })
//this.props.navigation.navigate('AudioRecording',{templateId:templateId, documentId: documentId});
} else {
this.props.setLoader(false);
this.handler('error','Error',this.props.audioRecordingResponse.message);
}
})
// }
// })
};
Please let me know if anyone having solution for the same.
I am not sure whether this answers your specific case, but this is how I send my code from a react native app:
import AudioRecord from 'react-native-audio-record';
import * as RNFS from 'react-native-fs'
.....
record = () => {
if (!this.state.recording) {
this.setState({recording: true}, () => {
AudioRecord.start()
})
} else {
AudioRecord.stop().then(r => {
this.setState({recording: false})
RNFS.readFile(r, 'base64') // r is the path to the .wav file on the phone
.then((data) => {
this.context.socket.emit('sendingAudio', {
sound: data
});
})
});
}
}
I use sockets for my implementation but you can use pretty much anything as all I am sending is a long string. On the server side I then decode the string as so:
export async function sendingAudio(data) {
let fileName = `sound.wav`
let buff = Buffer.from(data.sound, 'base64');
await fs.writeFileSync(fileName, buff)
}
So basically I create a wav file on the phone, then read it into a base64 encoding, send that to the server and on the server I decode it from base64 into a .wav file.
For Laravel I believe this could help you Decode base64 audio . Just dont save it as mp3 but a wav.

How to retreive image data in sqlite database in flutter?

I want to retrieve image data in sqlite. im using below code
var image = await ImagePicker.pickImage(source: imageSource);
List<int> bytes = await image.readAsBytes();
i want to take image and after save it sqlite.if can get and set image from sqlite database ?.
I found the solution in my question.
I'm getting the image from an image_picker and Encode it to BASE64 string value like below
Uint8List _bytesImage;
File _image;
String base64Image;
Future getImage() async {
var image2 = await ImagePicker.pickImage(
source: ImageSource.gallery,
);
List<int> imageBytes = image2.readAsBytesSync();
print(imageBytes);
base64Image = base64Encode(imageBytes);
print('string is');
print(base64Image);
print("You selected gallery image : " + image2.path);
_bytesImage = Base64Decoder().convert(base64Image);
setState(() {
_image=image2;
});
}
after creating an SQLite database dbhelper.dart file to retrieve String values and database model file Image.dart for the get and set the String values.
image.dart
class Image{
int id;
String image;
Employee(this.id, this.image);
Employee.fromMap(Map map) {
id= map[id];
image = map[image];
}
}
dbhelper.dart
class DBHelper {
static Database _db;
Future<Database> get db async {
if (_db != null) return _db;
_db = await initDb();
return _db;
}
initDb() async {
io.Directory documentsDirectory = await getApplicationDocumentsDirectory();
String path = join(documentsDirectory.path, "test.db");
var theDb = await openDatabase(path, version: 1, onCreate: _onCreate);
return theDb;
}
void _onCreate(Database db, int version) async {
// When creating the db, create the table
await db.execute(
"CREATE TABLE Imagedata(id INTEGER PRIMARY KEY, image TEXT)");
print("Created tables");
}
void saveImage(Imagedata imagedata) async {
var dbClient = await db;
await dbClient.transaction((txn) async {
return await txn.rawInsert(
'INSERT INTO Imagedata(id, image) VALUES(' +
'\'' +
imagedata.id+
'\'' +
',' +
'\'' +
imagedata.image +
'\'' +
')');
});
}
Future<List<Imagedata>> getMyImage() async {
var dbClient = await db;
List<Map> list = await dbClient.rawQuery('SELECT * FROM Imagedata');
List<Imagedata> images= new List();
for (int i = 0; i < list.length; i++) {
images.add(new Imagedata(list[i]["id"], list[i]["image"]));
}
print(images.length);
return images;
}
Future<int> deleteMyImage(Imagedata imagedata) async {
var dbClient = await db;
int res =
await dbClient.rawDelete('DELETE * FROM Imagedata');
return res;
}
}
last getting String value from the database and Decode String value to the Image file.
Getting image from database
Future<List<Employee>> fetchImageFromDatabase() async {
var dbHelper = DBHelper();
Future<List<Imagedata>> images= dbHelper.getImages();
return images;
}
after Decode string value to the Image file
String DecoImage;
Uint8List _bytesImage;
FutureBuilder<List<Imagedata>>(
future: fetchImageFromDatabase(),
builder: (context, snapshot) {
if (snapshot.hasData) {
return new
ListView.builder(
itemCount: snapshot.data.length,
itemBuilder: (context, index) {
DecoImage=snapshot.data[index].image;
_bytesImage = Base64Decoder().convert(DecoImage);
return new SingleChildScrollView(
child: Container(
child: _bytesImage == null
? new Text('No image value.')
: Image.memory(_bytesImage)
),
);
}
);
}
}
),
i think that is helpful for other flutter,sqlite developers
import 'dart:convert';
import 'dart:typed_data';
    Uint8List bytesImage1;
    bool bolWithImage1 = false;
    try {
      bytesImage1 =
          base64Decode(base64StringFromSql);
      bolWithImage1 = true;
    } catch (err) {}
i.e. if bolWithImage1 is true, the conversion is successful. You can then use image.memory(byteImage1, ......) to show the image in flutter.
You can also save the image as a BLOB (data type: UInt8List). Storing both as Blob (UInt8List) or String(with Base64encoder) in sqflite works. The key was to use MemoryImage instead of Image.memory. Otherwise you would get type 'Image' is not a subtype of type 'ImageProvider ' error.
//First create column in database to store as BLOB.
await db.execute('CREATE TABLE $photoTable($colId INTEGER PRIMARY KEY AUTOINCREMENT, $colmage BLOB)');
//User imagePicker to get the image
File imageFile = await ImagePicker.pickImage(source: ImageSource.camera, maxHeight: 200, maxWidth: 200, imageQuality: 70);
//Get the file in UInt8List format
Uint8List imageInBytes = imageFile.readAsBytesSync();
//write the bytes to the database as a blob
db.rawUpdate('UPDATE $photoTable SET $colImage = ?, WHERE $colId =?', [imageInBytes, colID]);
//retrieve from database as a Blob of UInt8List
var result = await db.query(photoTable, orderBy: '$colID ASC');
List<Photo> photoList = List<Photo>();
for (int i=0; i<result.length; i++){
photoList.add(Photo.fromMapObject(userMapList[i]));
}
//Map function inside Photo object
Photo.fromMapObject(Map<String, dynamic> map) {
this._id = map['id'];
this._imageFile = map['image'];
}
//Display the image using using MemoryImage (returns ImagePicker Object) instead of Image.memory (returns an Image object).
return Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
CircleAvatar(
backgroundImage: MemoryImage(Photo.image),
backgroundColor: Colors.blueGrey[50],
),
]);

Resources