文件上传php-[精选] 如何用PHP断点继续上传大文件?

学习与交流:

在现代网站应用中,上传文件是非常常见的。在任何语言中,通过使用一些工具,都可以实现文件上传的功能。但是,如果处理大文件上传的需求,还是有点麻烦的。

假如你此时正在上传一个很大的文件,大约一个小时过去了,进度是 90%。突然断网了或者浏览器崩溃了,上传的程序退出,你要再全部重新来过。真的很不爽,对不对?还有更让人郁闷的是,如果你的网速很慢,那么,无论你重来多少次,你都不可能上传成功。

phpstorm全家桶激活码,支持多台电脑,支持多个IDE工具
链接:http://web.52shizhan.cn/activity/fot8dn 
提取码:KGYU508TG4


在 PHP 中,我们可以尝试利用 tus 协议的断点续传功能来解决这个问题。
什么是 tus?
Tus 是一个基于 HTTP 的 文件断点续传开放协议。断点续传的意思是不管是用户自行中断,还是由于网络等原因的意外中断,都可以从中断的地方继续上传,而不用重新开始。

Tus 协议是在 2017 年5月被 Vimeo 采用的。
为什么用 tus?
引用 Vimeo 的博客:

我们之所以决定用 tus,是因为它能以简洁开放的形式,将文件上传的过程标准化。这种标准化有利于 API 的开发者更加专注于应用本身的逻辑,而非文件上传的过程。

使用这种方式上传的另一个好处是,你可以在笔记本上开始上传文件,然后又转到手机或者其他设备继续上传同一个文件,这可以极大地提升用户体验。

开始
第一步,加载依赖。
$ composer require ankitpokhrel/tus-php

tus-php是用于tus简历合约v1.0.0的纯PHP框架,完美实现了服务端与客户端的交互

更新:Vimeo 官方 PHP 库 v3 现在使用 TusPHP。

创建处理请求的服务器

您可以创建如下所示的服务器。

// server.php
$server   = new TusPhpTusServer('redis');
$response = $server->serve();
$response->send();
exit(0); // 退出当前 PHP 进程

您需要配置服务器以响应特定端点。 如果你使用Nginx,你可以这样配置:

# nginx.conf
location /files {
    try_files $uri $uri/ /path/to/server.php?$query_string;
}

假设我们服务器的URL是这样的,根据我们内部的Nginx配置,我们可以通过 访问我们的tus终端。

基于 RESTful 风格的端点配置:

# 获取有关服务器目前配置的信息
OPTIONS /files

# 检查上传的文件是否合法
HEAD /files/{upload-key}

# 创建
POST /files

# 修改
PATCH /files/{upload-key}

# 删除
DELETE /files/{upload-key}

如果你使用的是类似Laravel的框架,那么你不需要在配置文件中定义这个,你可以直接定义访问tus的基本端点的路由。 我们将在单独的教程中介绍详细信息。

使用tus-php客户端处理上传

服务器就位后,客户端可以分块上传文件。 让我们首先创建一个简单的 HTML 表单来获取用户输入。

<form action="upload.php" method="post" enctype="multipart/form-data">
    <input type="file" name="tus_file" id="tus-file" />
    <input type="submit" value="Upload" />
</form>

提交表单后,我们需要按照几个步骤来处理上传。

创建tus-php客户端对象

// Tus client
$client = new TusPhpTusClient('http://server.tus.local');

里面代码中的第一个参数是你的tus服务器地址。

2. 使用文件元数据初始化客户端

为了保证上传文件的唯一性,我们需要对每个上传的文件进行唯一标记。 这样文件上传php,当文件中断并随后上传时,服务器可以清楚地识别哪些片段属于同一个文件。 这个识别码可以自己指定,也可以由系统生成。

// 设置标识码和文件元数据
$client->setKey($uploadKey)
    ->file($_FILES['tus_file']['tmp_name'], 'your file name');

如果不想指定识别码,可以这样写,系统会手动生成:

$client->file($_FILES['tus_file']['tmp_name'], 'your file name');
$uploadKey = $client->getKey(); // Unique upload key

3.分块上传文件

// $chunkSize 是以字节为单位的,例如 5000000 等于 5 MB
$bytesUploaded = $client->upload($chunkSize);

当需要继续下一个块时,可以使用相同的识别码参数继续传输。

// 在下一个请求中续传文件
$bytesUploaded = $client->setKey($uploadKey)->upload($chunkSize);

所有文件上传完毕后,默认情况下,服务器会使用sha256来校准文件的总和,以确保不会丢失文件。

使用tus-js-client客户端处理文件上传

tus合约团队还开发了模块化文件上传插件Uppy。 该插件可以在官方tus-js-client和tus-php服务器之间建立连接。 也就是说我们可以使用php和js来实现文件上传。

uppy.use(Tus, {
  endpoint'https://server.tus.local/files/', // 你的 tus 服务器
  resume: true,
  autoRetry: true,
  retryDelays: [0100030005000]
})

分块上传

tus-php服务器支持串联扩展文件上传php,可以将多个上传的文件合并为一个文件。 为此,我们可以在客户端支持并行上传和非顺序分块文件上传。

使用tus-php实现分块上传

tus-partial-upload.php

<?php
// 文件唯一标识码
$uploadKey = uniqid();
$client->setKey($uploadKey)->file('/path/to/file''chunk_a.ext');
// 从第 1000  个字节开始上传 10000 字节
$bytesUploaded = $client->seek(1000)->upload(10000);
$chunkAkey     = $client->getKey();
// 从 第 0 个字节开始上传 10000 字节
$bytesUploaded = $client->setFileName('chunk_b.ext')->seek(0)->upload(1000);
$chunkBkey     = $client->getKey();
// 从第 11000 个字节  (10000 +  1000) 开始上传剩余的字节
$bytesUploaded = $client->setFileName('chunk_c.ext')->seek(11000)->upload();
$chunkCkey     = $client->getKey();
// 把分块上传的文件组合起来
$client->setFileName('actual_file.ext')->concat($uploadKey, $chunkAkey, $chunkBkey, $chunkCkey);

分段上传的完整示例


原文链接:

以上就是本文的全部内容,希望各位程序员努力提高个人技能。 最后,小编温馨提醒:每晚读书5分钟,每晚学习一点,每晚进步一点。

点个赞

我们走吧

PHP学习笔记-php文件形式上传-day06

1. PHP文件上传流程 2. 预定义变量$_FILES

预定义变量$_FILES用于获取上传文件的文件信息(上传文件名、上传文件类型、上传文件大小)。

如下:

提示:表单中文件控件对应的name值暂定为file-name(方便理解),下面的参数说明不再解释。

2.1. 文件上传状态码

$_FILES['file-name']['error'] 文件上传状态码

其中,error中的值为0,1,2,3,4,(当然是文件形式的上传过程)解释如下

文件上传状态码 状态码含义

文件上传成功,没有错误

上传文件大小超过php.ini中upload_max_filesizes上限

上传文件的大小超过表单隐藏字段中MAX_FILE_SIZE参数的上限

部分文件上传

文件上传失败表单未选择上传文件

2.2. 上传文件的实现函数is_uploaded_file()函数

语句格式:boolis_uploaded_file(stringfileName)

功能:判断文件名fileName是否为上传时形成的临时文件。 move_uploaded_file() 函数

语句格式:boolmove_uploaded_file(stringfileName,stringdestination)

功能:将名为fileName的临时文件链接到目标文件目的地。 如果上传时fileName不是临时文件,则返回false,函数不会执行任何功能。 (如果目的地已经存在,它将被覆盖)。 3. 文件上传的小计数器示例 3.1. 文件上传表单form1.php

首先,创建一个用于提交数据的表单页面(form1.php):

文件上传表单的提交方式必须为post,enctype必须设置为multipart/form-data

	<!-- 文件上传 表单提交方式必须是post ,其中的enctype 必须设置为 multipart/form-data-->
	<form action="uploadFiles.php" method="post" enctype="multipart/form-data">
	    作者:<input type="text" name="author" placeholder="请输入文章作者"><br>
	    标题:<input type="text" name="title" placeholder="请输入文章标题"><br>
	    类型:<select name="articleType">
	            <option value="--------请选择类型--------" disabled selected></option>
	            <option value="技术类">技术类</option>
	            <option value="日记类">日记类</option>
	            <option value="随笔类">随笔类</option>
	        </select><br>
	    内容:<textarea name="content"></textarea><br>
	    插图:<input type="file" name="articleImg"><br>
	    <input type="submit" value="提交">
	</form>

3.2 文件上传表单处理的php页面uploadFiles.php

第二步创建php页面uploadFiles.php,用于文件上传表单处理

<?php
	// 获取文件表单参数
	
	//回忆一下php文件表单处理流程
	
	//1.判断是否超过 post_max_size 的上限值,因为预处理器会做这些,如果超过了就将$_GET,$_POST,$_FILES被置为空数组
	//所以我们只需要直接判断post是否为空数组,即可判断
	
	if(empty($_POST)){
	    echo "提交的文件数据,超过了 post_max_size 的上限值,请修改php.ini或者将文件压缩重新提交";
	    header("location:http://localhost:81/form1.php");
	}
	
	//2.获取上传文件的文件信息,通过它的状态码来判断会在哪一步出现问题
	
	$upImg = $_FILES['articleImg']; // 获取文件数组
	$error = $upImg['error']; // 获取文件的状态码
	
	switch ($error){
	
	    case 0:
	        // error 为 0 表示上传成功
	        $upImgName = $upImg['name'];
	        $upImgTemp = $upImg['tmp_name'];// 获取文件上传的临时目录
	        $destUpImg = "uploadImage/".$upImgName;//设置文件保存的目录
	        // 然后使用 php 提供的两个函数在 临时文件删除之前保存到服务器上
	        move_uploaded_file($upImgTemp,$destUpImg);
	        echo "文件上传成功"."
"
; break; case 1: echo "上传的文件超过了 php.in 中 upload_max_filesize 中的上限值"."
"
; break; case 2: echo "上传的文件超过了form表单中隐藏域中的MAX_FILE_SIZE中的值"."
"
; echo "上传的文件大小不能超过".$_POST['MAX_FILE_SIZE']."字节
"
; break; case 3: echo "文件部分被上传,原因是 max_execution_time 设置过小或者网速太慢,可以检查以下重新去上传"."
"
; break; case 4: echo "上传文件失败,原因是没有选择上传文件"."
"
; break; } // 获取文章表单上传的普通文本信息 $author = $_POST['author']; $title = $_POST['title']; $articleType = $_POST['articleType']; $content = $_POST['content']; // 输出上传的信息 正好练练定界符, echo <<<div <p>作者:$author</p> <p>标题:$title</p> <p>文章类型:$articleType</p> <p>文章内容:$content</p> <p> <img src=$destUpImg> </p> div;

3.3 运行测试输出

这里之所以不写css是因为图片占满了整个屏幕文件上传 php文件上传 php,是因为我这里写的表格很粗糙只是为了说明原理和步骤。

3.4 上传文件时需要注意的一些php.ini配置

首先你需要打开自己的php.ini文件,检查post_max_size、upload_max_filesize、upload_tmp_dir,这个对应的配置是否符合你要上传的文件大小和目录。

最重要的是,你不必检查upload_tmp_dir,因为这个在php.ini中默认有注释,删除上面的注释,但设置你自己的临时目录名称。