fluttercandies / flutter_photo_manager

A Flutter plugin that provides images, videos, and audio abstraction management APIs without interface integration, available on Android, iOS, macOS and OpenHarmony.
https://pub.dev/packages/photo_manager
Apache License 2.0
681 stars 309 forks source link

[BUG] `AssetEntity.file` failed to cache videos #818

Closed Tom3652 closed 2 years ago

Tom3652 commented 2 years ago

Expect

I would like to know what is the impact of this error when using assetEntity.file for file upload (if it has any) :

flutter: PlatformException(Could not cache the video file., null, null, null)
flutter: 
#0      StandardMethodCodec.decodeEnvelope (package:flutter/src/services/message_codecs.dart:607:7)
#1      MethodChannel._invokeMethod (package:flutter/src/services/platform_channel.dart:167:18)
<asynchronous suspension>
#2      AssetEntity._getFile (package:photo_manager/src/types/entity.dart:675:26)
<asynchronous suspension>

-> I am using this assetEntity.file path to upload the content on my server.

I have made some retry logic if my users kill the app while uploading, so the upload restarts at the next app opened session. Some of them told me that they had not the file to upload anymore sometimes, and i saw in the logs that the file doesn't exist anymore.

The path looks like this : /private/var/mobile/Containers/Data/Application/166AFEFA-FC94-4321-8013-8AF74CAF2A27/tmp/.video/1661572400.150018_IMG_4786.MOV

Is it possible that the OS clears out everything on this path by itself ? Does it mean i have to copy the content of assetEntity.file in my app directory to make sure the file is not deleted for upload ?

Thanks a lot in advance

AlexV525 commented 2 years ago

Can you update the code for more detailed logs?

https://github.com/fluttercandies/flutter_photo_manager/blob/a684b80c63ce0508cb174c2c5061935140951bb4/ios/Classes/core/PMManager.m#L601

image

Tom3652 commented 2 years ago

Do you want me to log more my own code ?

Here is the way i am retrieving / displaying the video asset :

  VideoPlayerController? _controller;

  Future<void> _initVideoWithFile() async {
    LogManager.i("Getting file...");
    final File? mediaUrl = await widget.entity.file;
    if (mediaUrl != null) {
      _controller = VideoPlayerController.file(
        mediaUrl,
      )..initialize().then((_) => setState(() {
            _controller!.setLooping(true);
            _controller!.play();
          }));
    }
  }

  Future<void> _initVideoWithUrl() async {
    LogManager.i("Getting media url...");
    final String? mediaUrl = await widget.entity.getMediaUrl();
    if (mediaUrl != null) {
      _controller = VideoPlayerController.network(
        mediaUrl,
      )..initialize().then((_) => setState(() {
            _controller!.setLooping(true);
            _controller!.play();
          }));
    } else {
      _initVideoWithFile();
    }
  }

  Future<void> initPlayer() async {
    bool available = await widget.entity.isLocallyAvailable();
    LogManager.i("is locally available : $available");
    if (available) {
      _initVideoWithUrl();
    } else {
      _initVideoWithFile();
    }
  }

  @override
  void initState() {
    super.initState();
    initPlayer();
  }
AlexV525 commented 2 years ago

As you can see, Could not cache the video file is thrown within the file manager, which might have multiple reasons to fail, like insufficient disk spaces. We can know more when it logs more. I've added the detailed log in 2.3.0.

Tom3652 commented 2 years ago

Thanks @AlexV525 with your logs :

open on /private/var/mobile/Containers/Data/Application/8CC59DB8-3876-4731-AAE5-E6A4D0350336/tmp/.video/1662327887.005963_IMG_4805.MP4: File exists
[log] Error from outside Flutter : PlatformException(Could not cache the video file: Error Domain=NSCocoaErrorDomain Code=516 "Impossible de copier « IMG_4805.MP4 » vers « .video » : un élément porte déjà ce nom." UserInfo={NSSourceFilePathErrorKey=/var/mobile/Media/DCIM/114APPLE/IMG_4805.MP4, NSUserStringVariant=(
    Copy
), NSDestinationFilePath=/private/var/mobile/Containers/Data/Application/8CC59DB8-3876-4731-AAE5-E6A4D0350336/tmp/.video/1662327887.005963_IMG_4805.MP4, NSFilePath=/var/mobile/Media/DCIM/114APPLE/IMG_4805.MP4, NSUnderlyingError=0x2819cebb0 {Error Domain=NSPOSIXErrorDomain Code=17 "File exists"}}, null, null, null) 
 #0      StandardMethodCodec.decodeEnvelope (package:flutter/src/services/message_codecs.dart:653:7)
#1      MethodChannel._invokeMethod (package:flutter/src/services/platform_channel.dart:296:18)
<asynchronous suspension>
#2      AssetEntity._getFile (package:photo_manager/src/types/entity.dart:680:26)
<asynchronous suspension>

It's written : "Impossible de copier « IMG_4805.MP4 » vers « .video » : un élément porte déjà ce nom." -> Impossible to copy « IMG_4805.MP4 » to « .video » there is already an element with this name.

AlexV525 commented 2 years ago

Impossible to copy « IMG_4805.MP4 » to « .video » there is already an element with this name.

Great, will seek for possible solutions.

AlexV525 commented 2 years ago

Can you try to use 9710e10 and see if the issue still exists?

Tom3652 commented 2 years ago

Thanks i confirm that it works fine with your commit ! It seems that the load is even faster for the same videos