locked
How to copy a .png or .jpg file to LocalStorage? RRS feed

  • Question

  • User42522 posted

    I have a 'Access Denied' error in the following code that uses Media.Plugin to pick a photo from the pic library and PCL Storage plugin for copying it. Am I doing something wrong? Or is there any better way of doing it?

            private async void btnPickPicture_Clicked(object sender, EventArgs e)
            {
                bool b = await CrossMedia.Current.Initialize();
    
                if (CrossMedia.Current.IsPickPhotoSupported)
                {
                    MediaFile photoPicked = await CrossMedia.Current.PickPhotoAsync();
    
                    if (photoPicked != null)
                    {
                        await DisplayAlert("Photo Location", photoPicked.Path, "OK");
    
                        imgPicked.Source = ImageSource.FromStream(() =>
                        {
                            Stream streamPhoto = photoPicked.GetStream();
                            photoPicked.Dispose();
                            return streamPhoto;
                        });
    
                        await CopyPhotoAsync(photoPicked.Path);
                    }
                    else
                    {
                        await DisplayAlert("Pick a Photo", "No Photo selected.", "OK");
                    }
                }
                else
                {
                    await DisplayAlert("Pick a Photo", "Selecting a photo is not supported", "OK");
                }
            }
    
            private async Task CopyPhotoAsync (string photoFile)
            {
                IFileSystem fileSystem = FileSystem.Current;
                IFolder rootFolder = fileSystem.LocalStorage;
                try
                {
                    IFile pickedPhoto = await fileSystem.GetFileFromPathAsync(photoFile);
                    await pickedPhoto.MoveAsync(rootFolder.Path, NameCollisionOption.ReplaceExisting);
                }
                catch (Exception ex)
                {
                    await DisplayAlert("Copy Photo", ex.Message, "OK");
                }
            }
    
    Monday, May 16, 2016 5:29 PM

Answers

  • User179286 posted

    So you don't get an Exception, right? One thing that makes me nervous is this:

     string[] parsedPath = photoPicked.Path.Split('\\');
    

    I have not worked on IOS, but as IOS is a Unix System I guess the the pathj separatot won't be "\" You should use the Path. Methods of System.IO.

    Also It could be that you need special persmissions on iOS, but then I guess you would get a Exception. Did you check all Paths in the debugger? Does this code run on Android?

    • Marked as answer by Anonymous Thursday, June 3, 2021 12:00 AM
    Monday, May 23, 2016 9:38 AM

All replies

  • User37696 posted

    @ShantimohanElchuri,

    Are you having this issue on Android? If so, can you verify you added the correct permissions? Here is the documentation on what to add to your AndroidManifest.xml file.

    Monday, May 16, 2016 5:43 PM
  • User42522 posted

    No, it is in UWP part. I have the following Capabilities set:

    1. Internet (Client)
    2. Pictures Library
    3. Removable Storage
    Monday, May 16, 2016 6:50 PM
  • User42522 posted

    @DanielPlaisted or @DanielPlaisted.6736 , who is the author of the PCLStorage plugin? Can you provide some answer?

    Monday, May 16, 2016 7:24 PM
  • User179286 posted

    I see several issues in you code that make me nervous:

    ``` imgPicked.Source = ImageSource.FromStream(() => { Stream streamPhoto = photoPicked.GetStream(); photoPicked.Dispose(); return streamPhoto; });

                    await CopyPhotoAsync(photoPicked.Path);
    

    ``` You dispose photopicked in your delegate and pass it later on to CopyPhotoAsync.

    Also take into account that IMageSource.FromStream Disposes the stream that it get passed.

    Tuesday, May 17, 2016 8:21 AM
  • User42522 posted

    Thanks @ThomasBurkhart for pointing the issues. My take on those issues is:

    1. Yes, using it after disposing off an object is definitely crazy. I don't know then why the object is still available to CopyPhotoAsync(). Now I am disposing off the photoPicked after the call to CopyPhotoAsync(). But still I'm getting the 'Access is denied' error.
    2. Since I am not using the streamPhoto afterwards, I'm not worried about it being closed. As such this was only a demo / test project on how to use the plugin. So I just adopted the code from the Usage part of the documentation for the Media.Plugin.
    Tuesday, May 17, 2016 3:53 PM
  • User179286 posted

    I might have the reason for you problem. You are using File.Move, that actually tries to move the file, meaning it will delete the entry from the Imagefolder for which you might not have the necessary privileges.

    I make a copy in one of my App be reading the file into a MemoryStream and then store it at the new location, which works without problems.

    Wednesday, May 18, 2016 6:20 AM
  • User42522 posted

    Good lead for me @ThomasBurkhart . The file that I get in PCL project is IFile of the PCL Storage. It doesn't have any methods for writing a stream or even WriteFile. If I have to use MemoryStream then I will have to implement it through Dependency only I suppose.

    Can you share your file copy code? Is it applicable to all 3 platforms?

    Thursday, May 19, 2016 3:13 AM
  • User179286 posted

    Sure you can use PCLStorage to write files :-)

                var imageFile =
                    await
                        PCLStorage.FileSystem.Current.LocalStorage.CreateFileAsync(outPutFileName,
                            CreationCollisionOption.ReplaceExisting);
                var outStream = await imageFile.OpenAsync(FileAccess.ReadAndWrite);
                await memStream.CopyToAsync(outStream);
                outStream.Dispose();
    
    Thursday, May 19, 2016 6:10 AM
  • User42522 posted

    ThanQ... @ThomasBurkhart . At least there were no errors in my test project. Now I will implement it in my main project.

    Thursday, May 19, 2016 3:26 PM
  • User42522 posted

    @ThomasBurkhart Did you run your code in iOS? My implemented code for the CopyPhotoAsync() is given below. Unfortunately it is not working in iOS. The count of files in rootFolder is zero after running the CopyToAsync() method. What am I doing wrong?

            private async Task CopyPhotoAsync(MediaFile photoPicked)
            {
                IFileSystem fileSystem = FileSystem.Current;
                IFolder rootFolder = fileSystem.LocalStorage;
    
                string[] parsedPath = photoPicked.Path.Split('\\');
                string photoFileName = parsedPath[parsedPath.Length - 1];
    
                try
                {
                    using (Stream srcStream = photoPicked.GetStream())
                    {
                        IList<IFile> rootFolderFilesBef = await rootFolder.GetFilesAsync();
    
                        IFile destPhotoFile = await rootFolder.CreateFileAsync(photoFileName, CreationCollisionOption.ReplaceExisting);
                        Stream destStream = await destPhotoFile.OpenAsync(FileAccess.ReadAndWrite);
    
                        await srcStream.CopyToAsync(destStream);
                        destStream.Dispose();
    
                        IList<IFile> rootFolderFilesAft = await rootFolder.GetFilesAsync();
                    }
                }
                catch (Exception ex)
                {
                    await DisplayAlert("Copy Photo", ex.Message, "OK");
                }
            }
    
    Sunday, May 22, 2016 7:55 PM
  • User179286 posted

    So you don't get an Exception, right? One thing that makes me nervous is this:

     string[] parsedPath = photoPicked.Path.Split('\\');
    

    I have not worked on IOS, but as IOS is a Unix System I guess the the pathj separatot won't be "\" You should use the Path. Methods of System.IO.

    Also It could be that you need special persmissions on iOS, but then I guess you would get a Exception. Did you check all Paths in the debugger? Does this code run on Android?

    • Marked as answer by Anonymous Thursday, June 3, 2021 12:00 AM
    Monday, May 23, 2016 9:38 AM
  • User42522 posted

    @ThomasBurkhart Sorry, I forgot about Unix works with forward slash (getting old???). With considering the '/' it did copy the file.

    As such in my original project, I use a fixed filename for the destination. I wrote this test project as the copied file when set to Image.Source was not shown. May be I have some other issue with my code. That I will deal separately.

    ThanQ...

    Tuesday, May 24, 2016 7:16 PM
  • User179286 posted

    No worries, things today are so complex and we have to deal with such a broad range of technologies something like this is normal. I'm also one of the elders here around and sometime feel like a dinosaur ;-)

    Tuesday, May 24, 2016 8:53 PM