精华内容
下载资源
问答
  • tus协议
    2018-08-10 19:03:00

    原文地址:https://tus.io/protocols/resumable-upload.html

    摘要

        该协议提供一种基于 HTTP/1.1 和 HTTP/2 机制用于文件断点续传。

    核心协议

        核心协议描述如何继续中断的上传。这里假定你已经有一个用于上传的 RUL ,这个 URL 通常是由扩展协议 Creation创建。

        所有客户端和服务端必须实现核心协议。

        协议没有描述 RUL 的结构,而是留给协议的实现来决定。本文中所有展示的 URL 仅用于举例。

        此外,认证和授权的实现也留给服务端来决定。

    示例

        用一个请求头指明应当从什么地方开始续传上传。

        以下示例展示中断位置由70变为100

    请求

    HEAD /files/24e533e02ec3bc40c387f1a0e460e216 HTTP/1.1

    Host: tus.example.org

    Tus-Resumable: 1.0.0

    响应

    HTTP/1.1 200 OK

    Upload-Offset: 70

    Tus-Resumable: 1.0.0

     

        对于给定的中断位置,客户端使用 PATCH 方法来续传。

    请求

    PATCH /files/24e533e02ec3bc40c387f1a0e460e216 HTTP/1.1

    Host: tus.example.org

    Content-Type: application/offset+octet-stream

    Content-Length: 30

    Upload-Offset: 70

    Tus-Resumable: 1.0.0

     

    [remaining 30 bytes]

    响应

    HTTP/1.1 204 No Content

    Tus-Resumable: 1.0.0

    Upload-Offset: 100

     

    报文头

    Upload-Offset【上传偏移位置】

        请求和响应中的上传便宜位置表明资源的字节偏移量。该值必须是一个非负整数。

    Upload-Length【上传长度】

        请求和响应中的上传长度表明资源的字节数【不是一次请求上传的字节数】,该值必须是非负整数。

    Tus-Version【协议版本】

        响应头中的协议版本值必须是由逗号分隔的服务器支持的协议列表,列表中的第一个必须是服务器最希望的版本。

    Tus-Resumable

        Tus-Resumable 头除了 OPTIONS 请求外,每次请求和响应必须指明。Tus-Resumable

     值必须是客户端和服务器正在使用的协议版本。【更具体的说就是当前请求和响应使用的协议版本】

        如果服务端不支持客户端发过来的协议版本,服务端必须响应 412 Precondition Failed 状态,并且响应头中必须包括 Tus-Resumable,另外,服务端必须不处理这个请求。

    Tus-Extension【扩展协议】

        响应头中的 Tus-Extension 值必须是有逗号分隔服务端支持的扩展协议的列表。如果服务端不支持扩展协议,则这个头应当去掉。

    Tus-Max-Size

        协议头中的 Tus-Max-Size 值必须是非负整数用以表明整个上传最大允许的字节数【原文字面理解是上传资源的最大限制字节数,不是一次请求的最大限制字节数】,服务端如果有硬性限制应当在这个头中表明。

    X-HTTP-Method-Override

        如果这个请求头有值,则服务端必须使用这个值当做请求方法【Method】,而当前请求的实际请求方法必须忽略。客户端应当在其不支持 PATCH 或 DELETE 方法时使用该请求头。【这个头不是tus 创建的,http 原本就有,举个例子:客户端不能发生 PATCH 请求,于是发送一个 Get 请求,在 X-HTTP-Method-Override 头中设置值为 PATCH ,这个服务端就知道客户端想发的是 PATCH 请求】

    请求

    HEAD

        服务端在接收到 HEAD 请求后,其必须总是在响应头中包含 Upload-Offset 表明上传偏移位置,即便偏移位置是 0,或上传已经完成。如果知道上传资源的长度,服务端必须在 Upload-Length 指明长度。如果服务端没有找到上传的资源,服务端应当返回 404 Not Found、410 Gone 或 403 Forbidden,且没有 Upload-Offset 头。

        服务端必须在响应头中包含 Cache-Control: no-store 来阻止客户端或客户端代理从缓存中获取响应。

    PATCH

        服务端应当接受任何 PATCH 上传请求,并且将请求体中的内容放在 Upload-Offse 头指示的位置后。使用 PATCH 请求必须使用 Content-Type: application/offset+octet-stream 请求头,否则服务端应当响应 415 Unsupported Media Type 状态。

        Upload-Offset 报文头的值必须与资源的偏移量相等。出于并行上传考虑,可以使用 Concatenation 扩展协议。如果上传偏移量与资源实际偏移不相同,服务端应当返回 409 Conflict 状态,且不修改资源。

        如果 PATCH 请求没有包含 Content-Length 头,或者 Content-Length 值不是非负整数,服务端应当返回 400 Bad Request 状态。

        客户端应当在一个 PATCH 请求中发送所有未发送的字节,但是可能存在发送多个较小的请求的场景。一个这样的示例是使用了 Checksum 扩展协议。

        服务端必须响应 204 No Content 状态来表明成功处理 PATCH 请求。响应必须包含 Upload-Offset 报文头,当然必须使用更新后的值。更新后的值必须是上一个请求偏移量和接收内容的和。

        如果服务端接收到一个不存在资源的 PATCH 请求,应当返回 404 Not Found 状态。

        客户端和服务器应当尝试检测和处理可预见的网络错误,比如读写 socket 错误和读写超时,当连接超时应当关闭底层连接。

        服务端应当总是尝试存储尽可能多接收数据。

    OPTIONS

        一个 OPTIONS 请求可能被用于收集服务端当前的配置,一个成功的响应应当返回 204 No Content 或 200 OK 状态,并且必须包含 Tus-Version 响应头,它可能包含 Tus-Extension 和 Tus-Max-Size 头。

    示例

    请求

    OPTIONS /files HTTP/1.1

    Host: tus.example.org

    响应

    HTTP/1.1 204 No Content

    Tus-Resumable: 1.0.0

    Tus-Version: 1.0.0,0.2.2,0.2.1

    Tus-Max-Size: 1073741824

    Tus-Extension: creation,expiration

    扩展协议

    待补充

     

    转载于:https://www.cnblogs.com/850391642c/p/tus-Protocol.html

    更多相关内容
  • 前两天我采用技巧式方案基本实现大文件分片上传,这里只是重点在于个人思路和亲身实践,若在实际生产环境要求比较高的话肯定不行,仍存在一些问题需要深入处理,本文继续在之前基础上给出基于tus协议的轮子方案,本...
  • 引用Vimeo的博客: 我们之所以决定在上载堆栈中使用tus,是因为tus协议以简洁明了的方式标准化了上载文件的过程。这种标准化将使API开发人员可以将更多的精力放在其特定于应用程序的代码上,而不必将精力放在上传...

    曾经尝试过用PHP上传大文件吗?想知道您是否可以从上次中断的地方继续上传,而不会在遇到任何中断的情况下再次重新上传整个数据?如果您觉得这个场景很熟悉,请接着往下阅读。

    文件上传是我们几乎所有现代Web项目中的一项很常见的任务。在任何语言中,有了可用的工具,实现文件上传功能都不难。但是,对于大文件上传,这个事情还是有些让人头疼。

    假设您正在尝试上传相当大的文件。您已经等待了一个多小时,上传率为90%。然后突然,您的连接断开或浏览器崩溃。上传被中止,您需要从头开始上传。这很令人沮丧,不是吗?更糟糕的是,如果您的连接速度较慢,就像世界上许多地方一样,无论尝试多少次,每次都只能上传第一部分内容。无论你重来多少次,你都不可能上传成功。你的心态扛得住嘛?!?!
    在这里插入图片描述
    在这篇文章中,我们将尝试通过使用tus协议以可恢复块的形式上传文件来解决PHP中的此问题。

    首先什么是tus?

    Tus是用于可恢复文件上传的基于HTTP的开放协议。可恢复意味着可以在中断的地方继续工作,而不会在遇到任何中断的情况下再次重新上传整个数据。如果用户希望暂停,则中断可能会发生,或者在网络问题或服务器中断的情况下,偶然发生。

    Vimeo于2017年5月采用了 Tus协议。

    为什么是tus?

    引用Vimeo的博客:

    我们之所以决定在上载堆栈中使用tus,是因为tus协议以简洁明了的方式标准化了上载文件的过程。这种标准化将使API开发人员可以将更多的精力放在其特定于应用程序的代码上,而不必将精力放在上传过程本身上。

    通过这种方式上传文件的另一个主要好处是,您可以从笔记本电脑开始上传,甚至可以继续从移动设备或任何其他设备上载相同的文件,这可以极大地提升用户体验。
    基本的Tus架构
    入门

    从添加我们的依赖关系开始

    $ composer require ankitpokhrel/tus-php
    

    tus-php是用于tus可断续上传协议v1.0.0的纯PHP框架 服务器和客户端实现。
    tus-php-for用于tus可恢复上载协议v1.0.0的纯PHP服务器和客户端 github.com

    更新:Vimeo现在在其官方PHP库的v3 中将TusPHP 用于Vimeo API。

    创建一个服务器来处理我们的请求

    这就是简单服务器的外观。

    // server.php
    
    $server   = new \TusPhp\Tus\Server('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是http://server.tus.local。 因此,基于上面的nginx配置,我们可以使用http://server.tus.local/files访问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>
    

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

    1. 创建一个tus-php客户端对象

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

    上面代码中的第一个参数是您的 tus 服务器端点。

    2. 使用文件元数据初始化客户端
    为了确保上传文件的唯一性,我们需要使用一些标识符来识别即将到来的请求中的上传。为此,我们将必须生成一个唯一的上传密钥,该密钥可在以后用于恢复上传。您可以提供一个上传密钥,也可以让系统自己生成一个密钥。

    // 设置上传密钥和文件元数据
    
    $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。您可以使用uppy将正式的tus-js-client与tus-php服务器无缝集成。这意味着我们正在使用服务器的php实现和客户端的js实现。

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

    更多细节可以查看uppy的文档,还有些例子可以供你参考。

    分块上传

    tus-php 服务器支持 concatenation 扩展,并且可以把多次上传的文件合为一个文件。因此,我们可以在客户端支持并行上传以及非连续的分块文件上传。

    使用 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);
    

    分块上传的完整例子 在这里.

    最后说一下TUS 协议

    核心协议
    核心协议描述如何继续中断的上传。这里假定你已经有一个用于上传的 RUL ,这个 URL 通常是由扩展协议 Creation创建。
    所有客户端和服务端必须实现核心协议。
    协议没有描述 RUL 的结构,而是留给协议的实现来决定。本文中所有展示的 URL 仅用于举例。
    此外,认证和授权的实现也留给服务端来决定。

    示例
    用一个请求头指明应当从什么地方开始续传上传。
    以下示例展示中断位置由70变为100

    请求
    HEAD /files/24e533e02ec3bc40c387f1a0e460e216 HTTP/1.1
    Host: tus.example.org
    Tus-Resumable: 1.0.0

    响应
    HTTP/1.1 200 OK
    Upload-Offset: 70
    Tus-Resumable: 1.0.0
    对于给定的中断位置,客户端使用 PATCH 方法来续传。

    请求
    PATCH /files/24e533e02ec3bc40c387f1a0e460e216 HTTP/1.1
    Host: tus.example.org
    Content-Type: application/offset+octet-stream
    Content-Length: 30
    Upload-Offset: 70
    Tus-Resumable: 1.0.0
    [remaining 30 bytes]

    响应
    HTTP/1.1 204 No Content
    Tus-Resumable: 1.0.0
    Upload-Offset: 100

    Happy Coding!

    更多学习内容请访问从码农成为架构师的修炼之路

    以上内容希望帮助到大家,很多PHPer在进阶的时候总会遇到一些问题和瓶颈,业务代码写多了没有方向感,不知道该从那里入手去提升,对此我整理了一些资料,包括但不限于:分布式架构、高可扩展、高性能、高并发、服务器性能调优、TP6,laravel,YII2,Redis,Swoole、Swoft、Kafka、Mysql优化、shell脚本、Docker、微服务、Nginx等多个知识点高级进阶干货需要的可以免费分享给大家,需要的可以加入我的官方群点击此处。

    展开全文
  • 哥斯 用于纯Go客户端例package mainimport ( "os" "github.com/eventials/go-tus")func main () { f , err := os .... Close () // create the tus client. client , _ := tus . NewClient ( "https://tus.example.or
  • 【导读】前两天我采用技巧式方案基本实现大文件分片上传,这里只是重点在于个人思路和亲身实践,若在实际生产环境要求比较高的话肯定不行,仍存在一些问题需要深入处理,本文继续在之前基础上给出基于tus协议的轮子...
    【导读】前两天我采用技巧式方案基本实现大文件分片上传,这里只是重点在于个人思路和亲身实践,若在实际生产环境要求比较高的话肯定不行,仍存在一些问题需要深入处理,本文继续在之前基础上给出基于tus协议的轮子方案,本打算再次尝试利用.NET Core实现此协议,但在github上一搜索早在2016年就已有此协议对应的.NET和.NET Core方案,并且一直更新到最近的.NET Core 3.x版本,完全满足各位所需,本文是我写出的一点demo。

    基于tus协议实现断点续传演示

    基于tus协议前端脚本

    关于此协议实现原理这里不做阐述,请参照上述github地址自行了解,本文只是给出.NET Core方案下的基本demo,我们上传一个大文件然后通过进度显示上传进度以及对上传可暂停可继续,专业点讲就是断点续传,首先肯定是引入tus脚本和需要用到的bootstrap样式,我们将进度条默认隐藏,当上传时才显示,所以我们给出如下HTML。

    <div class="form-horizontal" style="margin-top:80px;">
        <div class="form-group" id="progress-group" style="display:none;">
            <div id="size"></div>
            <div class="progress">
                <div id="progress" class="progress-bar progress-bar-success progress-bar-animated progress-bar-striped" role="progressbar"
                     aria-valuemin="0" aria-valuemax="100">
                    <span id="percentage"></span>
                </div>
            </div>
        </div>
        <div class="form-group">
            <div class="col-md-10">
                <input name="file" id="file" type="file" />
            </div>
        </div>
        <div class="form-group">
            <div class="col-md-offset-2 col-md-10">
                <input type="submit" id="submit" value="上传" class="btn btn-success" />
                <input type="button" id="pause" value="暂停" class="btn btn-danger" />
                <input type="button" id="continue" value="继续" class="btn btn-info" />
            </div>
        </div>
    </div>
    


    接下来就是使用引入的tus脚本,也没什么太多要讲解的,直接上代码,这里稍微注意的是在如下元数据(metadata)属性对象定义给出实际文件名,便于在后台最终将上传的文件转换为目标文件,至少得知道文件扩展名,对吧。

    <script type="text/javascript">
        $(function () {
            var upload;
    
            //上传
            $('#submit').click(function () {
    
                $('#progress-group').show();
    
                var file = $('#file')[0].files[0];
    
                // 创建tus上传对象
                upload = new tus.Upload(file, {
                    // 文件服务器上传终结点地址设置
                    endpoint: "files/",
                    // 重试延迟设置
                    retryDelays: [0, 3000, 5000, 10000, 20000],
                    // 附件服务器所需的元数据
                    metadata: {
                        name: file.name,
                        contentType: file.type || 'application/octet-stream',
                        emptyMetaKey: ''
                    },
                    // 回调无法通过重试解决的错误
                    onError: function (error) {
                        console.log("Failed because: " + error)
                    },
                    // 上传进度回调
                    onProgress: onProgress,
                    // 上传完成后回调
                    onSuccess: function () {
                        console.log("Download %s from %s", upload.file.name, upload.url)
                    }
                })
    
                upload.start()
            });
    
            //暂停
            $('#pause').click(function () {
                upload.abort()
            });
    
            //继续
            $('#continue').click(function () {
                upload.start()
            });
    
            //上传进度展示
            function onProgress(bytesUploaded, bytesTotal) {
                var percentage = (bytesUploaded / bytesTotal * 100).toFixed(2);
                $('#progress').attr('aria-valuenow', percentage);
                $('#progress').css('width', percentage + '%');
    
                $('#percentage').html(percentage + '%');
    
                var uploadBytes = byteToSize(bytesUploaded);
                var totalBytes = byteToSize(bytesTotal);
    
                $('#size').html(uploadBytes + '/' + totalBytes);
            }
    
            //将字节转换为Byte、KB、MB等
            function byteToSize(bytes, separator = '', postFix = '') {
                if (bytes) {
                    const sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB'];
                    const i = Math.min(parseInt(Math.floor(Math.log(bytes) / Math.log(1024)).toString(), 10), sizes.length - 1);
                    return `${(bytes / (1024 ** i)).toFixed(i ? 1 : 0)}${separator}${sizes[i]}${postFix}`;
                }
                return 'n/a';
            }
        });
    
    </script>
    

    基于tus协议tusdotnet

    接下来进入后台,首先安装对应tus协议实现包,如下:

    接下来则是添加tus中间件,说白了就是对tus的配置,各种配置都可满足你所需,这里我只实现了文件上传完成后将上传文件转换为目标文件的处理,紧接着将如下实现tus配置以单例形式注入即可

    private DefaultTusConfiguration CreateTusConfiguration(IServiceProvider serviceProvider)
    {
        var env = (IWebHostEnvironment)serviceProvider.GetRequiredService(typeof(IWebHostEnvironment));
    
        //文件上传路径
        var tusFiles = Path.Combine(env.WebRootPath, "tusfiles");
    
        return new DefaultTusConfiguration
        {
            UrlPath = "/files",
            //文件存储路径
            Store = new TusDiskStore(tusFiles),
            //元数据是否允许空值
            MetadataParsingStrategy = MetadataParsingStrategy.AllowEmptyValues,
            //文件过期后不再更新
            Expiration = new AbsoluteExpiration(TimeSpan.FromMinutes(5)),
            //事件处理(各种事件,满足你所需)
            Events = new Events
            {
                //上传完成事件回调
                OnFileCompleteAsync = async ctx =>
                {
                    //获取上传文件
                    var file = await ctx.GetFileAsync();
    
                    //获取上传文件元数据
                    var metadatas = await file.GetMetadataAsync(ctx.CancellationToken);
                    
                    //获取上述文件元数据中的目标文件名称
                    var fileNameMetadata = metadatas["name"];
    
                    //目标文件名以base64编码,所以这里需要解码
                    var fileName = fileNameMetadata.GetString(Encoding.UTF8);
    
                    var extensionName = Path.GetExtension(fileName);
    
                    //将上传文件转换为实际目标文件
                    File.Move(Path.Combine(tusFiles, ctx.FileId), Path.Combine(tusFiles, $"{ctx.FileId}{extensionName}"));
                }
            }
        };
    }
    
    </script>
    

    然后获取并使用上述添加的tus配置服务

    app.UseTus(httpContext => Task.FromResult(httpContext.RequestServices.GetService<DefaultTusConfiguration>()));
    

    在脚本中我们看到有个endpoint属性,此属性表示上传到服务器的上传结点地址,因为在上到服务器时我们可能需对此请求进行额外处理,比如元数据中的文件名是否已提供等等,所以我们在使用结点映射时,添加对上述结点名称的映射,如下

    endpoints.MapGet("/files/{fileId}", DownloadFileEndpoint.HandleRoute);
    

    该映射第二个参数为RequestDelegate,这个参数用过.NET Core的童鞋都知道,这里我是直接拷贝该包的路由实现,如下:

    public static class DownloadFileEndpoint
    {
        public static async Task HandleRoute(HttpContext context)
        {
            var config = context.RequestServices.GetRequiredService<DefaultTusConfiguration>();
    
            if (!(config.Store is ITusReadableStore store))
            {
                return;
            }
    
            var fileId = (string)context.Request.RouteValues["fileId"];
            var file = await store.GetFileAsync(fileId, context.RequestAborted);
    
            if (file == null)
            {
                context.Response.StatusCode = 404;
                await context.Response.WriteAsync($"File with id {fileId} was not found.", context.RequestAborted);
                return;
            }
    
            var fileStream = await file.GetContentAsync(context.RequestAborted);
            var metadata = await file.GetMetadataAsync(context.RequestAborted);
    
            context.Response.ContentType = GetContentTypeOrDefault(metadata);
            context.Response.ContentLength = fileStream.Length;
    
            if (metadata.TryGetValue("name", out var nameMeta))
            {
                context.Response.Headers.Add("Content-Disposition",
                    new[] { $"attachment; filename=\"{nameMeta.GetString(Encoding.UTF8)}\"" });
            }
    
            using (fileStream)
            {
                await fileStream.CopyToAsync(context.Response.Body, 81920, context.RequestAborted);
            }
        }
    
        private static string GetContentTypeOrDefault(Dictionary<string, Metadata> metadata)
        {
            if (metadata.TryGetValue("contentType", out var contentType))
            {
                return contentType.GetString(Encoding.UTF8);
            }
    
            return "application/octet-stream";
        }
    }
    

    文件上传大小限制统一说明

    我们知道无论是.NET还是.NET Core对于文件上传大小都有默认限制大小,这里对.NET Core中文件大小各种环境配置做一个统一说明,如果你将.NET Core寄宿在IIS上运行,那么请修改web.config配置文件大小限制

    <system.webServer>
      <security>
        <requestFiltering>
          //若不配置,默认是28.6兆
          <requestLimits maxAllowedContentLength="1073741824" />
        </requestFiltering>
      </security>
    </system.webServer>
    

    如果在开发环境默认使用IIS运行应用程序,请通过如下根据实际情况配置文件上传大小

    services.Configure<IISServerOptions>(options =>
     {
          options.MaxRequestBodySize = int.MaxValue;
     });
    

    如果程序运行在Kestrel服务器,那么请通过如下根据实际情况配置文件上传大小

    services.Configure<KestrelServerOptions>(options =>
    {
         //若不配置,默认是30兆(没记错的话)
         options.Limits.MaxRequestBodySize = int.MaxValue; 
    });
    

    如果是通过表单上传文件,那么请通过如下根据实际情况配置文件上传大小

    services.Configure<FormOptions>(x =>
    {
         x.ValueLengthLimit = int.MaxValue;
        //如果不配置,默认是128兆(没记错的话)
         x.MultipartBodyLengthLimit = int.MaxValue; 
         x.MultipartHeadersLengthLimit = int.MaxValue;
    });
    

    为了更好体验可以再加上当前网络宽带情况或剩余多少分钟,更详细内容请参考:https://github.com/tusdotnet/tusdotnet 、https://github.com/tus/tus-js-client,关于大文件上传处理到此结束,希望对那些苦苦寻找最终解决方案而无助的童鞋们提供最佳轮子,谢谢。

    展开全文
  • 使用 tus-js-client 客户端处理文件上传 tus 协议的团队还开发了一个模块化的文件上传插件 Uppy。这个插件可以在官方 tus-js-client 和 tus-php 服务器之间建立连接。也就是说我们可以使用 php 配合 js 来实现...

    你是否曾经为大文件上传而苦恼?如果文件上传的过程中,因为某种原因中断了,是否可以从中断的位置继续上传,而不用重新上传整个文件?如果你有这样的困惑,那么请继续阅读下面的内容。

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

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

    在 PHP 中,我们可以尝试利用 tus 协议的断点续传功能来解决这个问题。

     

    什么是 tus?

    Tus 是一个基于 HTTP 的 文件断点续传开放协议。 断点续传的意思是不管是用户自行中断,还是由于网络等原因的意外中断,都可以从中断的地方继续上传,而不用重新开始。

    Tus 协议是在 2017 年5月被  Vimeo 采用的

     

    为什么用 tus?

    引用 Vimeo 的博客:

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

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

    图片: Tus 大致的工作流程

     

    开始

    第一步,加载依赖。

    $ composer require ankitpokhrel/tus-php

    tus-php 是用于 tus 断点续传协议 v1.0.0 的一个的纯 PHP 框架,完美实现了 服务端与客户端的交互 。

    更新: 现在 Vimeo  官方 PHP 库 的  v3 用的是  TusPHP

     

    创建一个处理请求的服务端

    你可以像下面这样创建一个服务端.

    // server.php
    
    $server   = new \TusPhp\Tus\Server('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 是 http://server.tus.local. 因此,基于我们上面的 Nginx 配置,我们可以通过 http://server.tus.local/files. 来访问到我们的 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>

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

    1. 创建一个 tus-php 客户端对象
    // Tus client
    
    $client = new \TusPhp\Tus\Client('http://server.tus.local');

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

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

    为了确保上传文件的唯一性,我们需要给每个上传的文件以唯一标识。这样在文件中断后续传的时候,服务器就可以很清晰地辨识出,哪几个片段是属于同一个文件得。这个标识码可以自己指定,也可以由系统生成。

    // 设置标识码和文件元数据
    
    $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: [0, 1000, 3000, 5000]
    })
    更多细节可以查看  uppy 的文档,  这里 还有些例子可以供你参考。

     

    分块上传

    tus-php 服务器支持 concatenation 扩展,可以把多次上传的文件合为一个文件。因此,我们可以在客户端支持并行上传以及非连续的分块文件上传。

    使用 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);

    分块上传的完整例子 在这里.

     

    总结

    由于 tus-php 项目 本身还出于初级阶段,后面可能还会有一些改动。在 example 文件夹里,有三个不同的例子供你参考。

    大厂必备面试题,请看到最后有很多

    面试12家公司,收获9个offer,2020年PHP 面试问题

     

    以上内容希望帮助到大家,很多PHPer在进阶的时候总会遇到一些问题和瓶颈,业务代码写多了没有方向感,不知道该从那里入手去提升,对此我整理了一些资料,包括但不限于:分布式架构、高可扩展、高性能、高并发、服务器性能调优、TP6,laravel,YII2,Redis,Swoole、Swoft、Kafka、Mysql优化、shell脚本、Docker、微服务、Nginx等多个知识点高级进阶干货需要的可以免费分享给大家,需要的可以加入我的官方群点击此处

    展开全文
  • 用于tus可恢复文件上传协议v100的纯PHP服务器和客户端
  • Tus 协议是在 2017 年5月被 Vimeo 采用的。   为什么用 tus? 引用 Vimeo 的博客:   我们之所以决定用 tus,是因为它能以简洁开放的形式,将文件上传的过程标准化。这种标准化有利于 API 的开发者...
  • tus是一个可续穿文件上传协议,它以Http协议为载体,统一了一个文件断点续传的标准。 这篇文章翻译自https://tus.io/ 目前该协议版本信息如下: Version: 1.0.0 (SemVer) Date: 2016-03-25 Authors: Felix ...
  • Spring Boot实现TUS协议实现文件断点上传 关于Tus TUS协议提供一种基于 HTTP/1.1 和 HTTP/2 机制用于文件断点续传。 举例 HEAD请求用来查询某个文件上传进度使用下面例子中一个文件总共100个Byte,已经传输了70个...
  • tus-js-client tus是基于HTTP的可恢复文件上传协议。 可恢复是指可以随时中断... 协议版本: 1.0.0 该分支包含tus-js-client v2。 如果您正在寻找先前的主要版本,之后又引入了,请查看。例input . addEventListener (
  • tus-java-client是一个库,用于使用tus协议将文件上传到支持该协议的任何远程服务器。 该库也与Android平台兼容,并且可以使用该API进行任何修改而直接使用。 提供了其他类,可以在Java库中使用这些类。用法 // ...
  • 它实现了核心1.0协议以及以下扩展: (和creation-defer-length ) 安装 # Gemfile gem "tus-server" , "~> 2.3" 用法 gem提供了一个Tus::Server 应用程序,您可以将其安装在主应用程序中。 如果您使用的是Rails,...
  • 于应用程序的服务器实现。 要上传大文件,请考虑改用 (Python ...from aiohttp_tus import setup_tus app = setup_tus ( web . Application (), upload_url = "/uploads" , upload_path = Path ( __file__ ). pa
  • Tus和go-fastdfs的踩坑之旅

    千次阅读 2019-03-18 15:30:00
    针对前者,本人会继续研究tus协议,想办法吃透解决;如果是后者,那么只能由go-fastdfs作者协助解决了 附上完整测试代码 public class TusUploadTest { private static final String UPLOAD_BIG_PATH = ...
  • 使用Tus协议上传文件时,第一个请求没有问题,第二个请求出现了无法代理直接访问接口域名的情况,多方排查没有发现前端有任何错误 解决 因为前端没有传过接口域名,所以肯定不是前端自己控制Tus发的请求,于是通过...
  • 通过实现打开的文件上传协议tus( ),可以实现暂停或恢复文件上传(在连接断开或重置后)的功能。 该库通过实现了tus v1.0.0协议的服务器端。 可以在找到该库的Javadoc。 支持以下Java版本:7、8、9、10和11。快速...

空空如也

空空如也

1 2 3 4 5 ... 19
收藏数 361
精华内容 144
关键字:

tus协议

友情链接: Desktop.zip