0

    文件太大上传不了?看这里,秒传

    2023.06.03 | admin | 212次围观

    前言

    相信很多开发者b站上传失败服务器错误,都做过文件上传的功能。简单的文件上传很容易,在PHP里两个函数就能搞定:

    第一个函数判断文件是否存在,第二个函数上传文件。

    但是如果上传的文件有几百M或几个G的时候,这样简单操作可能就不灵了,可能会出现timeout或内存溢出的情况。

    之所以会这样,是因为上传文件时服务器是先将文件内容保存在内存中,然后才保存到文件中。另外,服务器对单次上传请求有时间和内存的限制,内存耗尽或时间超时,上传请求会被终止。虽然这两个值也是可以调整的,但是由于实际上传的文件是未知的,所以你也不确定多大的值是合适的。另外,如果内存限制设置得太大,时间设置太长,当你上传一个大文件时,有可能会将服务器内存耗尽,拖垮整个服务。

    那如何解决大文件上传的问题呢?

    当然是从这前面说到的两个原因着手!既然是因为文件太大b站上传失败服务器错误,才导致请求耗时太长,内存占用太大,那我们可以将大文件分割成一个个小文件上传,也就是采用分片上传。

    首先是前端将大文件分片上传,然后是后端将所有分片按顺序合并起来。如下:

    前端分片我们可以使用webuploader.js组件,后端我们直接用Laravel框架即可。使用webuploader进行分片上传很简单,只需要配置几个参数即可,如下:

    其中,chunked表示是否开启分片上传;chunkSize表示分片的大小,单位字节;threads表示并发量。这里需要注意的是由于计算文件的md5值需要一定的时间,所以这里没有使用自动上传,而是将选择文件和上传分成了两步。

    后端部分需要接收file、chunks、chunk、md5、size几个参数,其中md5用于判断文件的唯一性,chunks、size用于判断分片是否上传完毕,如下:

    这里也有一点需要注意,那就是服务端合并文件的时候最好使用stream_copy_to_stream进行流式操作,而不要直接file_put_contents。因为流式操作是一点点的合并的,不需要把全部的内容放在内存里,这样可以避免在合并分片的时候内存溢出。

    另外,考虑到分片上传有可能存在部分成功的情况,因此,需要设置一个定时任务用于清除临时文件,以减少服务器的资源浪费。如下:

    如此,大文件上传的问题就解决了。

    虽然,这里使用PHP做服务端的演示,但是使用Java、Golang,依然可以参考本案例,因为原理基本一样。

    版权声明

    本文仅代表作者观点。
    本文系作者授权发表,未经许可,不得转载。

    发表评论