Files
13 min
save files from a flutter app introduction sometimes applications need to store data that is often too large to be stored inside a parseobject the most common use case is storing images, but you can also use it for documents, videos, music, and other binary data to store a file on parse, you should always associate the file with another data object so you can retrieve this file path when querying the object if you do not associate, the file will be stored, but you will not find them on the cloud another important tip is to give a name to the file that has a file extension this extension lets parse figure out the file type and handle it accordingly we should also mention that each upload gets a unique identifier, so there’s no problem uploading multiple files using the same name in flutter, parsefile and parsewebfile let you store and retrieve application files in the cloud that would this guide explains how to store and retrieve files in your flutter app to manage back4app cloud storage if you do not associate your file to a data object the file will become an orphan file and you wont be able to find it on back4app cloud prerequisites an app created https //www back4app com/docs/get started/new parse app on back4app note follow the new parse app tutorial https //www back4app com/docs/get started/new parse app to learn how to create a parse app on back4app an flutter app connected to back4app note follow the install parse sdk on flutter project https //www back4app com/docs/flutter/parse sdk/parse flutter sdk to create an flutter project connected to back4app a device (or virtual device) running android or ios in order to run this guide example you should set up the plugin image picker https //pub dev/packages/image picker properly do not forget to add permissions for ios in order to access images stored in device { btn target=” blank” rel=”nofollow”} carefully read the instructions for setting up the android and ios project goal create an flutter gallery app that uploads and displays images from back4app 1 understanding parsefile and parsewebfile class there are three different file classes in this parse sdk for flutter \<font color="#2166ae">parsefilebase\</font> is an abstract class, the foundation of every file class that this sdk can handle \<font color="#2166ae">parsefile\</font> extends \<font color="#2166ae">parsefilebase\</font> and is by default used as the file class on every platform (not valid for web) this class uses a \<font color="#2166ae">file\</font> from \<font color="#2166ae">dart\ io\</font> for storing the raw file \<font color="#2166ae">parsewebfile\</font> is the equivalent to \<font color="#2166ae">parsefile\</font> used at flutter web this class uses an \<font color="#2166ae">uint8list\</font> for storing the raw file the methods available on \<font color="#2166ae">parsefilebase\</font> to manipulate files \<font color="#2166ae">save()\</font> or \<font color="#2166ae">upload()\</font> for save file on cloud \<font color="#2166ae">download()\</font> for retrive file and store in local storage there are properties to get information from the saved file \<font color="#2166ae">url\</font> gets the file url it is only available after you save the file or after you get the file from a parse object \<font color="#2166ae">name\</font> gets the file name this is the filename given by the user before calling the \<font color="#2166ae">save()\</font> method after callint the method, the property receives a unique identifier 2 uploading an image to upload an image, you will only need to create a \<font color="#2166ae">parsefilebase\</font> instance and then call the \<font color="#2166ae">save\</font> method let’s do that in our \<font color="#2166ae">upload\</font> function 1 parsefilebase? parsefile; 2 3 if (kisweb) { 4 //flutter web 5 parsefile = parsewebfile( 6 await pickedfile! readasbytes(), 7 name 'image jpg'); //name for file is required 8 } else { 9 //flutter mobile/desktop 10 parsefile = parsefile(file(pickedfile! path)); 11 } 12 await parsefile save(); the above snippet creates and saves the image, and after the save completes, we associate it with a \<font color="#2166ae">parseobject\</font> called \<font color="#2166ae">gallery\</font> 1 final gallery = parseobject('gallery') 2 set('file', parsefile); 3 await gallery save(); 3 displaying images to display images, you need to get the image’s url to upload an image, you will only need to create a \<font color="#2166ae">parsefilebase\</font> instance and then call the \<font color="#2166ae">save\</font> method 1 parsefilebase? varfile = parseobject get\<parsefilebase>('file'); 2 3 return image network( 4 varfile! url!, 5 width 200, 6 height 200, 7 fit boxfit fitheight, 8 ); 4 upload and retrieve from flutter app let’s now use our example for uploading and displaying images in flutter app, with a simple interface open your flutter project, go to the \<font color="#2166ae">main dart\</font> file, clean up all the code, and replace it with 1 import 'dart\ io'; 2 3 import 'package\ flutter/cupertino dart'; 4 import 'package\ flutter/foundation dart'; 5 import 'package\ flutter/material dart'; 6 import 'package\ image picker/image picker dart'; 7 import 'package\ parse server sdk flutter/parse server sdk dart'; 8 9 void main() async { 10 widgetsflutterbinding ensureinitialized(); 11 12 final keyapplicationid = 'your app id here'; 13 final keyclientkey = 'your client key here'; 14 15 final keyparseserverurl = 'https //parseapi back4app com'; 16 17 await parse() initialize(keyapplicationid, keyparseserverurl, 18 clientkey keyclientkey, debug true); 19 20 runapp(materialapp( 21 title 'flutter storage file', 22 debugshowcheckedmodebanner false, 23 home homepage(), 24 )); 25 } 26 27 class homepage extends statefulwidget { 28 @override 29 homepagestate createstate() => homepagestate(); 30 } 31 32 class homepagestate extends state\<homepage> { 33 pickedfile? pickedfile; 34 35 list\<parseobject> results = \<parseobject>\[]; 36 double selecteddistance = 3000; 37 38 @override 39 widget build(buildcontext context) { 40 return scaffold( 41 body padding( 42 padding const edgeinsets all(16 0), 43 child column( 44 crossaxisalignment crossaxisalignment stretch, 45 children \[ 46 container( 47 height 200, 48 child image network( 49 'https //blog back4app com/wp content/uploads/2017/11/logo b4a 1 768x175 1 png'), 50 ), 51 sizedbox( 52 height 16, 53 ), 54 center( 55 child const text('flutter on back4app save file', 56 style textstyle(fontsize 18, fontweight fontweight bold)), 57 ), 58 sizedbox( 59 height 16, 60 ), 61 container( 62 height 50, 63 child elevatedbutton( 64 child text('upload file'), 65 style elevatedbutton stylefrom(primary colors blue), 66 onpressed () { 67 navigator push( 68 context, 69 materialpageroute(builder (context) => savepage()), 70 ); 71 }, 72 ), 73 ), 74 sizedbox( 75 height 8, 76 ), 77 container( 78 height 50, 79 child elevatedbutton( 80 child text('display file'), 81 style elevatedbutton stylefrom(primary colors blue), 82 onpressed () { 83 navigator push( 84 context, 85 materialpageroute(builder (context) => displaypage()), 86 ); 87 }, 88 )) 89 ], 90 ), 91 )); 92 } 93 } 94 95 class savepage extends statefulwidget { 96 @override 97 savepagestate createstate() => savepagestate(); 98 } 99 100 class savepagestate extends state\<savepage> { 101 pickedfile? pickedfile; 102 bool isloading = false; 103 104 @override 105 widget build(buildcontext context) { 106 return scaffold( 107 appbar appbar( 108 title text('upload fie'), 109 ), 110 body padding( 111 padding const edgeinsets all(12 0), 112 child column( 113 crossaxisalignment crossaxisalignment stretch, 114 children \[ 115 sizedbox(height 16), 116 gesturedetector( 117 child pickedfile != null 118 ? container( 119 width 250, 120 height 250, 121 decoration 122 boxdecoration(border border all(color colors blue)), 123 child kisweb 124 ? image network(pickedfile! path) 125 image file(file(pickedfile! path))) 126 container( 127 width 250, 128 height 250, 129 decoration 130 boxdecoration(border border all(color colors blue)), 131 child center( 132 child text('click here to pick image from gallery'), 133 ), 134 ), 135 ontap () async { 136 pickedfile? image = 137 await imagepicker() getimage(source imagesource gallery); 138 139 if (image != null) { 140 setstate(() { 141 pickedfile = image; 142 }); 143 } 144 }, 145 ), 146 sizedbox(height 16), 147 container( 148 height 50, 149 child elevatedbutton( 150 child text('upload file'), 151 style elevatedbutton stylefrom(primary colors blue), 152 onpressed isloading || pickedfile == null 153 ? null 154 () async { 155 setstate(() { 156 isloading = true; 157 }); 158 parsefilebase? parsefile; 159 160 if (kisweb) { 161 //flutter web 162 parsefile = parsewebfile( 163 await pickedfile! readasbytes(), 164 name 'image jpg'); //name for file is required 165 } else { 166 //flutter mobile/desktop 167 parsefile = parsefile(file(pickedfile! path)); 168 } 169 await parsefile save(); 170 171 final gallery = parseobject('gallery') 172 set('file', parsefile); 173 await gallery save(); 174 175 setstate(() { 176 isloading = false; 177 pickedfile = null; 178 }); 179 180 scaffoldmessenger of(context) 181 removecurrentsnackbar() 182 showsnackbar(snackbar( 183 content text( 184 'save file with success on back4app', 185 style textstyle( 186 color colors white, 187 ), 188 ), 189 duration duration(seconds 3), 190 backgroundcolor colors blue, 191 )); 192 }, 193 )) 194 ], 195 ), 196 ), 197 ); 198 } 199 } 200 201 class displaypage extends statefulwidget { 202 @override 203 displaypagestate createstate() => displaypagestate(); 204 } 205 206 class displaypagestate extends state\<displaypage> { 207 @override 208 widget build(buildcontext context) { 209 return scaffold( 210 appbar appbar( 211 title text("display gallery"), 212 ), 213 body futurebuilder\<list\<parseobject>>( 214 future getgallerylist(), 215 builder (context, snapshot) { 216 switch (snapshot connectionstate) { 217 case connectionstate none 218 case connectionstate waiting 219 return center( 220 child container( 221 width 100, 222 height 100, 223 child circularprogressindicator()), 224 ); 225 default 226 if (snapshot haserror) { 227 return center( 228 child text("error "), 229 ); 230 } else { 231 return listview\ builder( 232 padding const edgeinsets only(top 8), 233 itemcount snapshot data! length, 234 itembuilder (context, index) { 235 //web/mobile/desktop 236 parsefilebase? varfile = 237 snapshot data!\[index] get\<parsefilebase>('file'); 238 239 //only ios/android/desktop 240 / 241 parsefile? varfile = 242 snapshot data!\[index] get\<parsefile>('file'); 243 / 244 return image network( 245 varfile! url!, 246 width 200, 247 height 200, 248 fit boxfit fitheight, 249 ); 250 }); 251 } 252 } 253 }), 254 ); 255 } 256 257 future\<list\<parseobject>> getgallerylist() async { 258 querybuilder\<parseobject> querypublisher = 259 querybuilder\<parseobject>(parseobject('gallery')) 260 orderbyascending('createdat'); 261 final parseresponse apiresponse = await querypublisher query(); 262 263 if (apiresponse success && apiresponse results != null) { 264 return apiresponse results as list\<parseobject>; 265 } else { 266 return \[]; 267 } 268 } 269 } find your \<font color="#2166ae">applicationid\</font> and \<font color="#2166ae">client key\</font> credentials navigating to your app dashboard >settings >security and keys at back4app website https //www back4app com/ update your code in \<font color="#2166ae">main dart\</font> with both values of your project’s \<font color="#2166ae">applicationid\</font> and \<font color="#2166ae">clientkey\</font> in back4app keyapplicationid = \<font color="#2166ae">appid\</font> keyclientkey = \<font color="#2166ae">client key\</font> run the project, and the app will load as shown in the image conclusion at this point, you have uploaded image on back4app and displayed it in a flutter application