1

I have nextcloud running on my Raspberry Pi 4, which uses 32-bit architecture.

When trying to upload a file larger then 2147483647 bytes, the file is uploaded completely and is accessible through ssh. However when I try to access it in any way through the webclient it fails. The error seen in the webclient's logging is the following:

file_put_contents(): content truncated from 4118394086 to 2147483647 bytes at /var/www/html/nextcloud/lib/private/Files/Storage/Local.php#556

When I try to access the file this error message is logged:

Sabre\DAV\Exception\RequestedRangeNotSatisfiable: The start offset (0) exceeded the size of the entity (-176573210)

The file in question here is a .mp4 file, however i have been able to replicate the issue with other filetypes.

I have read that the 2GB upload limit for 32-bit architectures has been fixed, however I don't know why it might fail in my case.

marxlaml
  • 321
  • 2
  • 11

1 Answers1

2

Problem

Well you cant get around this by tweaking any config, since its a hard limit set by PHP (PHP_INT_MAX on 32-Bit architecure is 2G (2^(32-1)-1))

There is hope

You can patch manually or even better override the responsible nextcloud code:

patch manually (since you are not using composer this is what you probably wanna do)

// this one is pretty memory expensive, but works with resouce and string
// Test: 4GB file, 2GB chunks (at 32bits)
// 12GB memory usage! - hell no
public function file_put_contents($path, $data) {
    $bytesWritten = 0;
    foreach (explode(PHP_EOL, chunk_split($data, PHP_INT_MAX, PHP_EOL)) as $chunk) {
        $bytesWritten += file_put_contents($this->getSourcePath($path), $chunk, FILE_APPEND|LOCK_EX);
    }
    
    return $bytesWritten;
}

or

// better use this, in case $data is a resource - I dont know, you have to test it!
// Test: 4GB file, 1MB chunks
// 2MB memory usage - much better :)
public function file_put_contents($path, $data) {
    $bytesWritten = 0;
    while ($chunk = fread($data, 2**20)) {
        $bytesWritten += file_put_contents($this->getSourcePath($path), $chunk, FILE_APPEND|LOCK_EX);
    }

    return $bytesWritten;
}

In case you want to override (composer)

class PatchedLocal extends OC\Files\Storage\Local {
    public function file_put_contents($path, $data) {
        // same as above ...
    }
}

And here everything you need to know to force the autoloader to use your PatchedLocal. - As mentioned, you want to use composers PSR-4 implementation for this - via composer.json.

SirPilan
  • 4,649
  • 2
  • 13
  • 26
  • As promising as this looks, I received the same error (with a different line number throwing the error) regardless of which of the two methods I used. Since the line number changed I am sure the changes took effect... I wonder why this might be, since the change makes sense to me, how can I verify it was used correctly? – marxlaml Aug 09 '20 at 10:01
  • 1
    @marxlaml I found a small error in the second file_put_contents I used `$str` instead of `$data` in fread. If this still not works, try lowering the chunksize fom `2**20`(1MB) to `2**19`(512KB) etc until it works. Are you sure its exactly the same message? Please copy the new error (with the new line-number to your question.) – SirPilan Aug 09 '20 at 15:47
  • Sorry for the incredibly late reply, but sadly nothing I tried worked. Your suggestions made sense to me but caused the same error as before. What I did to fix the problem, is to install the 64-bit Raspbian OS version. – marxlaml Aug 18 '20 at 13:54