Many times in our applications we need to upload files as fast as we can. So the best way to achieve this is using each platform’s own native apis which will speed up considerably our requests.
Recently, I just released a plugin for uploading files by doing a multipart request FileUploader Plugin for Xamarin and Windows
To start using it install the plugin in your native projects and PCL if applies.
Usage
You can upload files using the path or bytes. Also, can add headers and parameters for the multipart request. (Headers and parameters are optional in case you don’t need either of them for your request).
Upload file using file path
CrossFileUploader.Current.UploadFileAsync("<URL HERE>", new FilePathItem("<REQUEST FIELD NAME HERE>","<FILE PATH HERE>"), new Dictionary<string, string>()
{
{"<HEADER KEY HERE>" , "<HEADER VALUE HERE>"}
}
);
Upload file using file bytes
CrossFileUploader.Current.UploadFileAsync("<URL HERE>", new FileBytesItem("<REQUEST FIELD NAME HERE>","<FILE BYTES HERE>","<FILE NAME HERE>"), new Dictionary<string, string>()
{
{"<HEADER KEY HERE>" , "<HEADER VALUE HERE>"}
}
);
iOS
In order to allow receiving feedback of upload completion when application on background, you should do the following on the AppDelegate.cs
/**
* Save the completion-handler we get when the app opens from the background.
* This method informs iOS that the app has finished all internal processing and can sleep again.
*/
public override void HandleEventsForBackgroundUrl(UIApplication application, string sessionIdentifier, Action completionHandler)
{
FileUploadManager.UrlSessionCompletion = completionHandler;
}
Roadmap
There is still some work to do:
- Android background uploading support
- Binary upload support
- Handling File Upload Queue
- FTP Upload support
For more information look at the repository here: https://github.com/CrossGeeks/FileUploaderPlugin
Hope this helps someone.
Happy coding!
14 Comments
Hi I’ve got a scenario where I need to upload a Large Video file to an ASPX page in Xamarin.Forms. The response header will then contain the VideoIdentifier . Your Response object is of type FileUploadResponse and doesn’t provide me with a way of accessing the headers. Basically I’m trying to implement the following code using your plugin. The code below is from an old UWP app. Any suggestions?
string _VideoIdentifier = string.Empty;
Uri _FullMediaManagerURI = new Uri(mediaManagerURI, “Video/VideoUpload.aspx”);
List _Parts = new List();
BackgroundTransferContentPart _BinaryPart = new BackgroundTransferContentPart(“File0”, __File.Name);
_BinaryPart.SetFile(__File);
_Parts.Add(_BinaryPart);
BackgroundTransferContentPart _JSONPart = new BackgroundTransferContentPart(“JSONData”);
_JSONPart.SetText(videoRequestModelJSON);
_Parts.Add(_JSONPart);
BackgroundUploader _BackgroundUploader = new BackgroundUploader();
UploadOperation _UploadOperation = await _BackgroundUploader.CreateUploadAsync(_FullMediaManagerURI, _Parts);
await _UploadOperation.StartAsync();
ResponseInformation _ResponseInformation = _UploadOperation.GetResponseInformation();
if (_ResponseInformation.Headers.ContainsKey(“VideoIdentifier”))
{
_VideoIdentifier = _ResponseInformation.Headers[“VideoIdentifier”];
}
return _VideoIdentifier;
Here a very hot fix:
https://www.nuget.org/packages/Plugin.FileUploader/1.3.9-beta
Just came out of the oven! Should include the response headers let me know if helps
Right now doesn’t include the response headers. But will include them on next release, thanks for pointing this out!
Here a very hot fix:
https://www.nuget.org/packages/Plugin.FileUploader/1.3.9-beta
Just came out of the oven! Should include the response headers let me know if helps
Thanks a lot Rendy. Just tried it on UWP and it works! Thanks a lot. Will try it on iOS & Droid later today and will let you know if I get any problems.
Just tried it on Android and I get the following error in the FileUploadResponse.Message. property. I have installed the Plugin on to both the PCL and the platform project.
Java.Lang.ClassNotFoundException: md57d3d8062e3e9a64ad1430263be8244a6.CountingRequestBody —> Java.Lang.ClassNotFoundException: Didn’t find class “md57d3d8062e3e9a64ad1430263be8244a6.CountingRequestBody” on path: DexPathList[[zip file “/data/app/com.pinewood.techplus-a4niPqfg5FrZ1nH7iRQUkg==/base.apk”],nativeLibraryDirectories=[/data/app/com.pinewood.techplus-a4niPqfg5FrZ1nH7iRQUkg==/lib/arm, /system/fake-libs, /data/app/com.pinewood.techplus-a4niPqfg5FrZ1nH7iRQUkg==/base.apk!/lib/armeabi-v7a, /system/lib, /vendor/lib]]
— End of inner exception stack trace —
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw () [0x0000c] in :0
at Java.Interop.JniEnvironment+StaticMethods.CallStaticObjectMethod (Java.Interop.JniObjectReference type, Java.Interop.JniMethodInfo method, Java.Interop.JniArgumentValue* args) [0x00069] in :0
at Android.Runtime.JNIEnv.CallStaticObjectMethod (System.IntPtr jclass, System.IntPtr jmethod, Android.Runtime.JValue* parms) [0x0000e] in :0
at Android.Runtime.JNIEnv.CallStaticObjectMethod (System.IntPtr jclass, System.IntPtr jmethod, Android.Runtime.JValue[] parms) [0x00017] in :0
at Android.Runtime.JNIEnv.FindClass (System.String classname) [0x0003d] in :0
at Android.Runtime.JNIEnv.FindClass (System.Type type) [0x00084] in :0
at Android.Runtime.JNIEnv.AllocObject (System.Type type) [0x00000] in :0
at Android.Runtime.JNIEnv.StartCreateInstance (System.Type type, System.String jniCtorSignature, Android.Runtime.JValue* constructorParameters) [0x00007] in :0
at Android.Runtime.JNIEnv.StartCreateInstance (System.Type type, System.String jniCtorSignature, Android.Runtime.JValue[] constructorParameters) [0x00017] in :0
at OkHttp.RequestBody..ctor () [0x00043] in :0
at Plugin.FileUploader.CountingRequestBody..ctor (OkHttp.RequestBody body, System.String tag, Plugin.FileUploader.ICountProgressListener listener) [0x00000] in C:\Plugins\FileUploader\src\Plugin.FileUploader.Android\CountingRequestBody.cs:24
at Plugin.FileUploader.FileUploadManager.MakeRequest (System.String url, System.String tag, OkHttp.MultipartBuilder requestBodyBuilder, System.Collections.Generic.IDictionary`2[TKey,TValue] headers) [0x00000] in C:\Plugins\FileUploader\src\Plugin.FileUploader.Android\FileUploadManager.cs:222
at Plugin.FileUploader.FileUploadManager+c__DisplayClass23_0.b__0 () [0x00082] in C:\Plugins\FileUploader\src\Plugin.FileUploader.Android\FileUploadManager.cs:62
— End of managed Java.Lang.ClassNotFoundException stack trace —
java.lang.ClassNotFoundException: md57d3d8062e3e9a64ad1430263be8244a6.CountingRequestBody
at java.lang.Class.classForName(Native Method)
at java.lang.Class.forName(Class.java:453)
Caused by: java.lang.ClassNotFoundException: Didn’t find class “md57d3d8062e3e9a64ad1430263be8244a6.CountingRequestBody” on path: DexPathList[[zip file “/data/app/com.pinewood.techplus-a4niPqfg5FrZ1nH7iRQUkg==/base.apk”],nativeLibraryDirectories=[/data/app/com.pinewood.techplus-a4niPqfg5FrZ1nH7iRQUkg==/lib/arm, /system/fake-libs, /data/app/com.pinewood.techplus-a4niPqfg5FrZ1nH7iRQUkg==/base.apk!/lib/armeabi-v7a, /system/lib, /vendor/lib]]
at dalvik.system.BaseDexClassLoader.findClass(BaseDexClassLoader.java:125)
at java.lang.ClassLoader.loadClass(ClassLoader.java:379)
at java.lang.ClassLoader.loadClass(ClassLoader.java:312)
… 2 more
Enable multidex
Thanks, That worked for small video files. But when I tried a large video clip I get an out of memory exception. The file I tried to upload was 218MB. (Android)
Java.Lang.OutOfMemoryError: Failed to allocate a 2064 byte allocation with 640 free bytes and 640B until OOM, max allowed footprint 268435456, growth limit 268435456
Try playing with these properties in Android:
FileUploadManager.UploadTimeoutUnit = TimeUnit.Minutes;
FileUploadManager.SocketUploadTimeout = 10;
FileUploadManager.ConnectUploadTimeout = 5;
What’s the largest video that you have tested on Android? I’m failing to upload anything larger than 150MB on Android. I’ve tried playing with the TimeOut properties as per your suggestion but not had much luck.
Can we use this plugin in Xamarin native Android and iOS. and is there any sample for Xamarin Native.
yes you can use it. I don’t have a native sample but is used in the same way
Thank you very much for your fast reply, ok I will try it. and for uploading multiple files at once do se need to call following code repeatedly or we can pass list of FilePathItem directly?
CrossFileUploader.Current.UploadFileAsync(serviceUrl, new FilePathItem(“file”, filepath), new Dictionary()
{
{“Authorization” , “adfaf”}
}
right
Comments are closed.