使用PHP发送文件时可恢复下载? [英] Resumable downloads when using PHP to send the file?

查看:122
本文介绍了使用PHP发送文件时可恢复下载?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我们正在使用PHP脚本来隧道传输文件下载,因为我们不想公开可下载文件的绝对路径:

We are using a PHP scripting for tunnelling file downloads, since we don't want to expose the absolute path of downloadable file:

header("Content-Type: $ctype");
header("Content-Length: " . filesize($file));
header("Content-Disposition: attachment; filename=\"$fileName\"");
readfile($file);

遗憾的是,我们注意到,最终用户无法恢复通过此脚本传递的下载。

Unfortunately we noticed that downloads passed through this script can't be resumed by the end user.

有没有办法通过这样一个基于PHP的解决方案来支持可恢复的下载?

Is there any way to support resumable downloads with such a PHP-based solution?

推荐答案

您需要做的第一件事是在所有响应中发送 Accept-Ranges:bytes 头,告诉客户您支持部分内容。然后,如果接收到 Range:bytes = xy 头的请求(使用 x y 为数字),您可以解析客户端请求的范围,像往常一样打开文件,寻找 x 字节,然后发送下一个 y - x 个字节。还设置了对 HTTP / 1.0 206 Partial Content 的响应。

The first thing you need to do is to send the Accept-Ranges: bytes header in all responses, to tell the client that you support partial content. Then, if request with a Range: bytes=x-y header is received (with x and y being numbers) you parse the range the client is requesting, open the file as usual, seek x bytes ahead and send the next y - x bytes. Also set the response to HTTP/1.0 206 Partial Content.

没有测试任何东西,这可以工作,更多或更少:

Without having tested anything, this could work, more or less:

$filesize = filesize($file);

$offset = 0;
$length = $filesize;

if ( isset($_SERVER['HTTP_RANGE']) ) {
    // if the HTTP_RANGE header is set we're dealing with partial content

    $partialContent = true;

    // find the requested range
    // this might be too simplistic, apparently the client can request
    // multiple ranges, which can become pretty complex, so ignore it for now
    preg_match('/bytes=(\d+)-(\d+)?/', $_SERVER['HTTP_RANGE'], $matches);

    $offset = intval($matches[1]);
    $length = intval($matches[2]) - $offset;
} else {
    $partialContent = false;
}

$file = fopen($file, 'r');

// seek to the requested offset, this is 0 if it's not a partial content request
fseek($file, $offset);

$data = fread($file, $length);

fclose($file);

if ( $partialContent ) {
    // output the right headers for partial content

    header('HTTP/1.1 206 Partial Content');

    header('Content-Range: bytes ' . $offset . '-' . ($offset + $length) . '/' . $filesize);
}

// output the regular HTTP headers
header('Content-Type: ' . $ctype);
header('Content-Length: ' . $filesize);
header('Content-Disposition: attachment; filename="' . $fileName . '"');
header('Accept-Ranges: bytes');

// don't forget to send the data too
print($data);

我可能错过了一些明显的东西,我绝对忽略了一些潜在的错误来源,但是应该是一个开始。

I may have missed something obvious, and I have most definitely ignored some potential sources of errors, but it should be a start.

有一个部分内容的描述在这里,我在文档页面上找到了关于 fread

There's a description of partial content here and I found some info on partial content on the documentation page for fread.

这篇关于使用PHP发送文件时可恢复下载?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆