2013-10-24 20 views
0

我有以下代碼使用帶進度條的XMLHttpRequest下載文件。內容長度沒有在請求但設置標題...下載後文件不會打開

編輯:

的目的是展示千兆速度和通用的10 Mbps連接之間的差。用戶將一個大型視頻文件全部下載到Mac上。

進度條在頁面上顯示,文件在幾秒鐘內保存到磁盤...然後用戶啓用硬件開關,限制到10Mbps並再次下載,這次肯定會中止330MB文件的傳輸。

PHP(的download.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() + '%'); 
} 

我的要求包含了除其在$ filsize是呼應的Content-Length的每一個頭......讀330581733( 330MB和一些變化)。我的進度函數使用確切的數字進行測試,但應該是evt.total;

第一部分:爲什麼Content-Length頭不可用?

第二部分:下載完成後,它爲什麼不打開,它到底在哪裏?

+0

youi無法使用ajax將文件下載到操作系統。 ajax獲取字符串或blob或數組緩衝區數據。如果需要,您可以自行獲取這些數據並自行下載。嘗試http://danml.com/js/download.js在較新的瀏覽器中將字符串下載到指定文件中。 – dandavis

+0

我不同意... XMLHttpRequests可用於檢索信息和文件系統,然後存儲到客戶端硬盤上的文件。 Chrome彈出一個窗口,問我是否可以將一個大文件保存到我的磁盤上,這樣我就走在了正確的軌道上。 – zgr024

+0

除非您從文件夾運行頁面,否則XMLHttpRequests不提供對客戶端硬盤驅動器的訪問權限,在這種情況下,瀏覽器通常允許只讀訪問,但這不會幫助您保存任何內容。如果下載的文件應該在下載菜單中。如果它不在那裏,那麼這個文件就會出現在內存中,或許是由某個臨時文件支持的。由於您的服務器設置配置,只需將視頻網址傳遞給window.open(url)即可下載。大多數瀏覽器在下載時顯示進度條。 – dandavis

回答

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已經被替換爲靜態文件大小。

+0

這只是我說,你不能,我待命的聲明。 FileSaver.js腳本與我之前發佈的鏈接基本相同... – dandavis

+0

您之前引用的腳本不會與FileSaver.js執行相同的操作,並且不會與我嘗試完成的操作配合使用,不過謝謝您。上面寫在答案中的腳本適用於我所需要的所以沒有爭論的地方......但是......將數據框放在頁面上或單擊生成的標籤與使用文件系統存儲不同已經下載的數據。 blob也已經由XMLHttpRequest生成,並且對MSBlobBuilder的引用也不起作用,因爲我們使用的是演示的Mac,因此沒有IE 10+。 (以前沒有提到) – zgr024

+0

認爲一些簡單的拼寫錯誤使得這個比需要更容易混淆。很高興你找到了什麼。我可能應該將blob添加到我的下載腳本中。 filesaver.js使用窗口而不是一個框架,並且如果可用的話,它們都首先使用。不管:你確定chrome使用filewriter分支嗎?我認爲這是背後的權限牆... – dandavis

相關問題