【问题标题】:file_put_contents truncates content to max int on 32-bit phpfile_put_contents 在 32 位 php 上将内容截断为最大 int
【发布时间】:2020-08-08 19:09:09
【问题描述】:

我的 Raspberry Pi 4 上运行 nextcloud,它使用 32 位架构。

当尝试上传大于 2147483647 字节的文件时,该文件已完全上传并可通过 ssh 访问。但是,当我尝试通过 webclient 以任何方式访问它时,它会失败。在 webclient 的日志中看到的错误如下:

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

当我尝试访问该文件时,会记录此错误消息:

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

这里有问题的文件是一个 .mp4 文件,但是我已经能够用其他文件类型复制这个问题。

我了解到 32 位架构的 2GB 上传限制已修复,但我不知道为什么在我的情况下它可能会失败。

【问题讨论】:

    标签: php nextcloud


    【解决方案1】:

    问题

    你不能通过调整任何配置来解决这个问题,因为它是 hard limit set by PHP(32 位架构上的 PHP_INT_MAX 是 2G (2^(32-1)-1))

    有希望

    您可以手动修补,甚至更好地覆盖responsible nextcloud code

    手动打补丁(因为你没有使用作曲家,这可能是你想要做的)

    // 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;
    }
    

    // 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;
    }
    

    如果你想覆盖(作曲家)

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

    以及here 强制自动加载器使用您的PatchedLocal 所需的一切。 - 如前所述,您希望为此使用 composers PSR-4 实现 - 通过 composer.json。

    【讨论】:

    • 尽管看起来很有希望,但无论我使用两种方法中的哪一种,我都会收到相同的错误(使用不同的行号引发错误)。由于行号已更改,我确信更改已生效...我想知道为什么会这样,因为更改对我有意义,我如何验证它是否正确使用?
    • @marxlaml 我在第二个 file_put_contents 中发现了一个小错误,我在 fread 中使用了 $str 而不是 $data。如果这仍然不起作用,请尝试将块大小从 2**20(1MB) 降低到 2**19(512KB) 等,直到它起作用。你确定它是完全相同的信息吗?请复制新错误(在您的问题中添加新的行号。)
    • 很抱歉回复得太晚了,但遗憾的是我没有尝试过任何工作。您的建议对我来说很有意义,但导致了与以前相同的错误。我解决问题的方法是安装 64 位 Raspbian OS 版本。
    猜你喜欢
    • 1970-01-01
    • 2012-02-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-08-31
    • 2015-08-03
    相关资源
    最近更新 更多