0

In the DidPickDocument event of UIDocumentPickerViewController I try to import/write the selected file into the app's local Documents directory. This works fine with "small" files (e.g < 100MB) using a subclassed UIDocument class with overriden

 public override bool LoadFromContents(NSObject contents, string typeName, out NSError outError)
    {

       outError = null;

        if (contents != null)
        {
            Content = ((NSData)contents).ToArray();

        }

...

...and by calling

 MySubclassedDoc mySubclassedDoc = new MySubclassedDoc (nsurl);
 bool success = await mySubclassedDoc.OpenAsync();
 File.WriteAllBytes("targetFile.xyz", mySubclassedDoc.Content);

But if the file is larger (eg. 400MB) the app crashes before LoadFromContents is called because of insufficent memory (RAM).

So there need to be a way to stream the selected file directly to a file. How can you do this using the given NSUrl ?

fritz
  • 427
  • 1
  • 5
  • 13

2 Answers2

0
  • why don’t you just clone the file over to your Documents directory before reading it instead of deserializing the contents and reserializing them?
  • your code seems really inefficient. If your files can be 400MB you should clearly not load all the contents into memory. I guess you must have very large binary objects in the files if they can be 400MB ; try mmapping the file and storing pointers to the individual objects instead?
Thomas Deniau
  • 2,488
  • 1
  • 15
  • 15
  • I was fixated on UiDocument (which is recommended when accessing files returned from the document picker on various web sites, eg the xamarin ones), so I did not see the simple solution using StartAccessingSecurityScopedResource and simple copy from a to b. – fritz Apr 24 '18 at 09:16
0

Since you have got the url, there's no need to convert it to NSData then store the data to a file. We can just use this url with NSFileManager like:

url.StartAccessingSecurityScopedResource();
string docPath = NSSearchPath.GetDirectories(NSSearchPathDirectory.DocumentDirectory, NSSearchPathDomain.User)[0];
string filePath = Path.Combine(docPath, "fileName.type");

NSError error;

NSFileManager fileManager = new NSFileManager();
fileManager.Copy(url.Path, filePath, out error);
url.StopAccessingSecurityScopedResource();

In this way we can store the file to our app's own document directory.

Ax1le
  • 6,563
  • 2
  • 14
  • 61