1

我有以下代码使用带有进度条的 XMLHttpRequest 下载文件。

编辑:

目的是演示千兆速度和普通 10 Mbps 连接之间的差异。用户在 Mac 上下载一个大型视频文件。

页面上显示进度条,文件在几秒钟内保存到磁盘...然后用户启用硬件开关以限制为 10Mbps 并再次下载,这一次肯定会中止 330MB 文件的传输。

PHP(下载.php):

<?
    $file='/path/to/some/video.mp4';

    header('Content-Description: File Transfer');
    header('Content-Type: video/mp4');
    header('Content-Disposition: attachment; filename='.basename($file));
    header('Content-Transfer-Encoding: binary');
    header('Content-Length: ' . filesize($file));
    header('Expires: 0');
    header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
    header('Pragma: public');
    ob_clean();
    flush();
    readfile($file);
?>

JavaScript:

var req = new XMLHttpRequest();
req.onprogress=updateProgress;
req.open('GET', 'download', true);
req.setRequestHeader("Content-Type","video/mp4");
req.onreadystatechange = function (aEvt) {  
    if (req.readyState == 4) {
        ...
    }
};  
req.send();

function updateProgress (evt) {
    console.log(evt);
    var percentComplete = Math.round(evt.loaded * 100 / 330581733);
    $('#downloadProgress').val(percentComplete);
    $('#progressVal').html(percentComplete.toString() + '%');
}

我的请求包含除了 Content-Length 之外的所有标头,当 $filsize 回显时...读取 330581733 (330MB 和一些更改)。我的进度功能使用确切的数字进行测试,但应该是 evt.total;

第一部分:为什么 Content-Length 标头不可用?

第二部分:下载完成后为什么打不开,去哪里了?

4

1 回答 1

0

我通常不会回答我自己的问题,但既然每个人都说这是不可能的,我想证明你们都错了......

首先你需要从你的脚本中引用... FileSaver.js

window.requestFileSystem  = window.requestFileSystem || window.webkitRequestFileSystem;
window.storageInfo = window.storageInfo || window.webkitStorageInfo;

// Request access to the file system for persistent storage of up to 1GB (1024^3)
navigator.webkitPersistentStorage.requestQuota (1024*1024*1024, function(grantedBytes) {
    console.log ('requestQuota: ', arguments); // FOR DEBUGGING
    window.webkitRequestFileSystem(window.PERSISTENT, grantedBytes, function(fs) {
        console.log ('fs: ', arguments); // FOR DEBUGGING
    }, errorHandler);
}, errorHandler);

req = new XMLHttpRequest(); 
req.onprogress=updateProgress;
req.open('GET', '/path/to/php/download', true);
req.setRequestHeader("Content-Type","video/mp4");
req.responseType = "blob";
req.onreadystatechange = function (aEvt) {  
    if (req.readyState == 4) {
        saveAs(req.response, "filename.mp4"); // DEFINED IN FileSaver.js
    }
}
req.send(null);

// PROGRESS BAR UPDATE
function updateProgress (evt) {
    var percentComplete = Math.round(evt.loaded * 100 / evt.total);
    $('#downloadProgress').val(percentComplete);
} 

这将允许页面上的进度条并将保存到本地下载目录。

注意:目前仅适用于 Chrome。测试版本:30.0.1599.101(Win 7)

Chrome 会在加载带有存储请求的页面时显示一条消息,询问客户端是否可以将大文件保存到磁盘。

另外值得注意的是,Content-Length 仍然没有出现在请求中,并且 updateProgress 中的 evt.total 已被替换为静态文件大小。

于 2013-10-24T20:16:28.317 回答