working with File uploads and display images in Flutter Parse Back4App

Amit Shukla
3 min readJul 17, 2024

--

Service Delivery Management App

welcome back friends,

In our previous blog, we presented an expedited demonstration of the Ride or Service Delivery Management application, which utilizes the Flutter platform coupled with the Parse back-end service by Back4App.

You can access the complete source code here.

In case you prefer video blogs, here is YouTube video tutorial.

If you are finding this blog for the first time, please visit previous blogs for a quick demo, about how to setup your project, build first hand UI pages. Implement Dark/Light Mode functionality, implement multilingual functionality, data model and dynamic data validators and implemented user authentication pages etc.

In this section, we will start building File upload and File display functionality. We’ll write code to upload and display images, allowing you to bring your digital creations to contribute.

let’s first add required packages to support file upload process.

flutter pub add image_picker

now import these packages.

import 'package:image_picker/image_picker.dart';
import 'package:parse_server_sdk_flutter/parse_server_sdk_flutter.dart';
import 'dart:io';
import 'package:flutter/foundation.dart';

add two Flutter Elevated Buttons to call image picker and display images. This code allow users to upload and view their documents.

ElevatedButton(
onPressed: () {
Navigator.push(context,
MaterialPageRoute(builder: (context) => SavePage()),);
},
child: const Text("upload documents")),
ElevatedButton(onPressed: () {
Navigator.push(context,
MaterialPageRoute(builder: (context) => DisplayPage()),);
},
child: const Text("display documents")),

add two state widgets, to upload and display images.

class SavePage extends StatefulWidget {
@override
_SavePageState createState() => _SavePageState();
}

class _SavePageState extends State<SavePage> {
PickedFile? pickedFile;
bool isLoading = false;
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Upload Fie'),
),
body: Padding(
padding: const EdgeInsets.all(12.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
SizedBox(height: 16),
GestureDetector(
child: pickedFile != null
? Container(
width: 250,
height: 250,
decoration:
BoxDecoration(border: Border.all(color: Colors.blue)),
child: kIsWeb
? Image.network(pickedFile!.path)
: Image.file(File(pickedFile!.path)))
: Container(
width: 250,
height: 250,
decoration:
BoxDecoration(border: Border.all(color: Colors.blue)),
child: Center(
child: Text('Click here to pick image from Gallery'),
),
onTap: () async {
PickedFile? image =
await ImagePicker().getImage(source: ImageSource.gallery);
if (image != null) {
setState(() {
pickedFile = image;
});
}
},
),
SizedBox(height: 16),
Container(
height: 50,
child: ElevatedButton(
child: Text('Upload file'),
style: ElevatedButton.styleFrom(primary: Colors.blue),
onPressed: isLoading || pickedFile == null
? null
: () async {
setState(() {
isLoading = true;
});
ParseFileBase? parseFile;
if (kIsWeb) {
//Flutter Web
parseFile = ParseWebFile(
await pickedFile!.readAsBytes(),
name: 'image.jpg'); //Name for file is required
} else {
//Flutter Mobile/Desktop
parseFile = ParseFile(File(pickedFile!.path));
}
await parseFile.save();
final gallery = ParseObject('Gallery')
..set('file', parseFile);
await gallery.save();
setState(() {
isLoading = false;
pickedFile = null;
});
ScaffoldMessenger.of(context)
..removeCurrentSnackBar()
..showSnackBar(SnackBar(
content: Text(
'Save file with success on Back4app',
style: TextStyle(
color: Colors.white,
),
),
duration: Duration(seconds: 3),
backgroundColor: Colors.blue,
));
},
))
],
),
),
);
}
}
class DisplayPage extends StatefulWidget {
@override
_DisplayPageState createState() => _DisplayPageState();
}
class _DisplayPageState extends State<DisplayPage> {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Display Gallery"),
),
body: FutureBuilder<List<ParseObject>>(
future: getGalleryList(),
builder: (context, snapshot) {
switch (snapshot.connectionState) {
case ConnectionState.none:
case ConnectionState.waiting:
return Center(
child: Container(
width: 100,
height: 100,
child: CircularProgressIndicator()),
);
default:
if (snapshot.hasError) {
return Center(
child: Text("Error..."),
);
} else {
return ListView.builder(
padding: const EdgeInsets.only(top: 8),
itemCount: snapshot.data!.length,
itemBuilder: (context, index) {
//Web/Mobile/Desktop
ParseFileBase? varFile =
snapshot.data![index].get<ParseFileBase>('file');
//Only iOS/Android/Desktop
/*
ParseFile? varFile =
snapshot.data![index].get<ParseFile>('file');
*/
return Image.network(
varFile!.url!,
width: 200,
height: 200,
fit: BoxFit.fitHeight,
);
});
}
}
}),
);
}
Future<List<ParseObject>> getGalleryList() async {
QueryBuilder<ParseObject> queryPublisher =
QueryBuilder<ParseObject>(ParseObject('Gallery'))
..orderByAscending('createdAt');
final ParseResponse apiResponse = await queryPublisher.query();
if (apiResponse.success && apiResponse.results != null) {
return apiResponse.results as List<ParseObject>;
} else {
return [];
}
}
}

Please do not forget to like and bookmark this article and subscribe to my YouTube and X accounts for more content.

--

--

Amit Shukla
Amit Shukla

Written by Amit Shukla

Build and Share Quality code for Desktop and Mobile App Software development using Web, AI, Machine Learning, Deep Learning algorithms. Learn, Share & Grow.

No responses yet