Press "Enter" to skip to content

Plugin for uploading files in Xamarin and Windows

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!

9 Comments

  1. Sergei Weerasuriya Sergei Weerasuriya

    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;

  2. Rendy Rendy

    Right now doesn't include the response headers. But will include them on next release, thanks for pointing this out!

    • Sergei Weerasuriya Sergei Weerasuriya

      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.

  3. Sergei Weerasuriya Sergei Weerasuriya

    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

  4. Rendy Rendy

    Enable multidex

  5. Sergei Weerasuriya Sergei Weerasuriya

    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

    • Rendy Rendy

      Try playing with these properties in Android:

      FileUploadManager.UploadTimeoutUnit = TimeUnit.Minutes;
      FileUploadManager.SocketUploadTimeout = 10;
      FileUploadManager.ConnectUploadTimeout = 5;

Leave a Reply

Your email address will not be published. Required fields are marked *