Studyxnet / FilePicker-Plugin-for-Xamarin-and-Windows

FilePicker Plugin for Xamarin and Windows
MIT License
74 stars 52 forks source link

Error getting value from 'DataArray' #30

Closed riandesign closed 7 years ago

riandesign commented 7 years ago

I tested it on iOS and I got this error: System.Exception: Error getting value from 'DataArray' on 'Plugin.FilePicker.Abstractions.FileData'.

My code:

try {
     FileData filedata = await CrossFilePicker.Current.PickFile();
} catch (Exception ex) {
     throw new Exception(ex.Message);
}
elmernocon commented 7 years ago

@riandesign , Hi it seems this is caused by line 71 in FilePickerImplementation.cs.

Changing it to OnFilePicked (new FilePickerEventArgs (dataBytes, filename, pathname)); should fix it, because line 141 in FilePickerImplementation.cs expects a FilePath to create the filestream. tcs?.SetResult (new FileData (e.FilePath, e.FileName, () => File.OpenRead (e.FilePath)));

@jfversluis any thoughts?

riandesign commented 7 years ago

@elmernocon , but I don't have the variable pathname. Thus, it doesn't exist in the context. What shoul I do in this case?

elmernocon commented 7 years ago

@riandesign , this should do the trick.

string filename = doc.LocalizedName;
string pathname = doc.FileUrl?.ToString();

// iCloud drive can return null for LocalizedName.
if (filename == null)
{
     // Retrieve actual filename by taking the last entry after / in FileURL.
     // e.g. /path/to/file.ext -> file.ext

     // filesplit is either:
     // 0 (pathname is null, or last / is at position 0)
     // -1 (no / in pathname)
     // positive int (last occurence of / in string)
     var filesplit = pathname?.LastIndexOf ('/') ?? 0;

     filename = pathname?.Substring (filesplit + 1);
}
jfversluis commented 7 years ago

@elmernocon great work! If you could pour this into an PR I will check it out somewhere today or tomorrow and if it looks good, I can merge it in.

riandesign commented 7 years ago

@elmernocon @jfversluis I still got the same error: System.Exception: Error getting value from 'DataArray' on 'Plugin.FilePicker.Abstractions.FileData'.

elmernocon commented 7 years ago

@riandesign , hmm, did you recompile?

riandesign commented 7 years ago

@elmernocon, yes. I rebuilt the DLLs.

riandesign commented 7 years ago

@elmernocon @jfversluis I realized the problem is not with null FilePath. Maybe FilePath is wrong, not null. I tried the code below and I still got the same error:

...
private Task<FileData> TakeMediaAsync () {
    ...
    Handler = (s, e) => {
        ...
        if (e != null && e.FilePath != null)
            // I also tested e.FilePath != String.empty
            // So, FilePath is not empty or null
            tcs.SetResult(new FileData(e.FilePath, e.FileName, () => File.OpenRead(e.FilePath)));
        else
            tcs.SetResult(null);
    ...
riandesign commented 7 years ago

@elmernocon @jfversluis any idea?

elmernocon commented 7 years ago

@riandesign , Hi, can you try these changes?

In the class FileData

  1. Add the field: private byte[] _dataArray = null;
  2. Change the property 'DataArray' GET to:
    public byte[] DataArray
    {
     get { return _dataArray; }
    }
  3. Add/replace a/the new/existing constructor with:
    public FileData (byte[] dataArray, string fileName, string filePath)
    {
     _dataArray = dataArray;
     _fileName = fileName;
     _filePath = filePath;
    }
  4. Optional: You can get rid of the members related to _streamGetter or _dispose.

the reasoning for this is we're already getting and passing the dataArray (byte[]) but it's not being used. see:

so now with the changes to FileData replace the following lines with:

I think this is caused by this: var securityEnabled = e.Url.StartAccessingSecurityScopedResource (); with FileData not having access to the "caged" resource it's failing in getting the byte[] value. this is just a guess though.

@jfversluis any thoughts?

riandesign commented 7 years ago

@elmernocon I can't do this: FilePickerImplementation (iOS) line 141: tcs?.SetResult (new FileData (e.DataArray, e.FileName, e.FilePath));

Because FilePickerEventArgs doesn't have e.DataArray. However, it has e.FileByte;

And it worked like a charm! Now, I'm able to pick files on iOS.

I appreciate a lot your help, @elmernocon ! Thank you very much. Any thing you need, please tell me.

elmernocon commented 7 years ago

@riandesign Hi, yeah missed that on my part, fixed the comment above :)

Quick question, were you able to make the document picker appear on an iPad Simulator / iPad?

riandesign commented 7 years ago

@elmernocon I haven't test on Simulator. I've tested it on iPhone device.

elmernocon commented 7 years ago

@riandesign if possible can you test it on an iPad Simulator?

msarun007 commented 7 years ago

` private async void btnUpload_Clicked(object sender, EventArgs e) { FileData fileData = await CrossFilePicker.Current.PickFile(); Byte[] byteArray = fileData.DataArray; // when i select pdf or doc from GoogleDrive Its getting DataArray = empty;// await CrossFilePicker.Current.SaveFile(fileData); if (fileData.FileName == string.Empty) { string filepath1 = await DependencyService.Get().SaveFiles("uploadedfile.pdf", byteArray); await DisplayAlert("Downloaded File path", filepath1, "ok");

        }
        else
        {
            string fileName = fileData.FileName;
            string filepath = await DependencyService.Get<ISaveFile>().SaveFiles(fileName, byteArray);
            await DisplayAlert("Downloaded File path", filepath, "ok");
            var fstream = new MemoryStream(byteArray);
            imgSelected.Source = ImageSource.FromStream(() => fstream);
        }

    }`

when i select pdf or doc from GoogleDrive Its getting DataArray = empty;//

divvugarimella commented 5 years ago

hi just add permissions in your

in manifest file and public override void OnRequestPermissionsResult(int requestCode, string[] permissions, [GeneratedEnum] Android.Content.PM.Permission[] grantResults) { PermissionsImplementation.Current.OnRequestPermissionsResult(requestCode, permissions, grantResults); base.OnRequestPermissionsResult(requestCode, permissions, grantResults); } in mainactivity.cs

@divya morampudi