Can't get file content when using remote storage

My app works fine when Nextcloud has all files stored on local storage, on the server’s hard drive. However, when a user configures his Nextcloud to use remote storage, like Amazon’s S3, my app throws multiple errors caused by file_get_contents() not finding the file.

With local storage I can get file content like this:

$fileContent = $this->view->file_get_contents("/" . $this->userSession->getUser()->getUID() . "/files/my_app/temp_dir/" . $filename);

This method uses the path relative to the data directory. It works fine with local storage, but with remote storage, the file is not actually in that path, in the ‘data’ directory. So, that path becomes invalid and file_get_contents()fails. Even an absolute path like /var/www/nextcloud/data/username/files/my_app/temp_dir/ . $filename wouldn’t work, because, as I said, with remote storage, the file isn’t actually there. Nextcloud stores the path to the remote file in the database and maps that path to the regular Nextcloud path.

To solve this problem I would use the file_get_contents method of the Filesystem class which uses paths relative to the Nextcloud base directory, like this:

$fileContent = $this->filesystem->file_get_contents("/my_app/temp_dir/" . $filename);

but unfortunately this doesn’t work either. I get the “Call to a member function file_get_contents() on null” error.

How can I make file_get_contents() work with remote storage ?

I think what you’re looking for this:

  • Use only OCP APIs (p = public)
  • Use the Node/Files API - OCP\Files\* {e.g. File, Folder, IRootFolder}

Examples:

https://cloud.nextcloud.com/s/iyNGp8ryWxc7Efa?dir=/6%20Developing%20a%20complete%20app%20with%20a%20navigation%20bar%20and%20database

1 Like

Thank you so much, jtr ! I really appreciate your help !

I used the 3 classes that you suggested:

use OCP\Files\File;
use OCP\Files\Folder;
use OCP\Files\IRootFolder;

I got the content of a file like this:

$getfile = $this->folder->get("/my_app/temp_dir/" . $somefile);
$fileContent = $getfile->getContent();

I saved the file content obtained like that to a different file in this way:

$targetfile = "/my_app/other_dir/" . $otherfile;
$target = $this->folder->newFile($targetfile);
$target->putContent($fileContent);

I got the names of the files inside the /my_app/temp_dir directory like this:

$gettempdir = $this->folder->get("/my_app/temp_dir");
$filesindir = $gettempdir->getDirectoryListing();

$filesnames = [];
foreach ($filesindir as $fileInfo){
         $filesnames[] = $fileInfo->getName();
}

I deleted files like this:

$path = "/path/to/file/to/delete"; // relative to root (All files) folder
$userFolder = $this->rootFolder->getUserFolder($this->userSession->getUser()->getUID());
$removefile = $userFolder->get($path)->delete();

And I opened files for reading like this:

$userFolder = $this->rootFolder->getUserFolder($this->userSession->getUser()->getUID());
$getfileopen = $userFolder->get("/my_app/some_dir/" . $fileName );
$opnfl = $getfileopen->fopen('r');

In this way, I used paths relative to the “All files” folder (root folder) for every user and consequently, even if Nextcloud used remote storage and the files were not located inside the /var/www/nextcloud/data/username/files directory of each user, the mentioned functions worked.

1 Like