我終於找到了我的主要問題的答案: 上傳完成後,在我的操作被調用之前,這3分鐘的等待期間發生了什麼?
在這篇文章中這一切都解釋得很清楚: The Rails Way - Uploading Files
「當瀏覽器上傳文件,它能編碼一種叫做‘多默’格式內容(它是被使用的格式相同當你發送電子郵件附件時)爲了讓你的應用程序對該文件做些什麼,rails必須撤銷這個編碼。要做到這一點,需要讀取巨大的請求體,並將每行與幾個正則表達式進行匹配。這可能是慢得令人難以置信,並使用一個巨大的CPU和內存的容量。」
我試着在帖子中提到的modporter Apache模塊。唯一的問題是,模塊和其相應的插件,分別爲4年前寫的,並且他們的網站不再運行,幾乎沒有任何文檔。
與modporter,我想指定我的NFS掛載的目錄作爲PorterDir,希望它可以將文件傳遞給NAS沒有從臨時目錄複製任何額外的內容,但是由於這個模塊似乎忽略了我指定的PorterDir,所以我無法得到這麼多,並且正在返回一個完全不同的路徑給我動作。最重要的是,它返回的路徑根本不存在,所以我不知道我的上傳實際發生了什麼。
我的解決方法
,我得問題迅速解決,所以我現在其中包括以分塊處理文件上傳相應的JavaScript/Ruby代碼寫的有點哈克的解決方案去了。
JS例:
var MAX_CHUNK_SIZE = 20000000; // in bytes
window.FileUploader = function (opts) {
var file = opts.file;
var url = opts.url;
var current_byte = 0;
var success_callback = opts.success;
var progress_callback = opts.progress;
var percent_complete = 0;
this.start = this.resume = function() {
paused = false;
upload();
};
this.pause = function() {
paused = true;
};
function upload() {
var chunk = file.slice(current_byte, current_byte + MAX_CHUNK_SIZE);
var fd = new FormData();
fd.append('chunk', chunk);
fd.append('filename', file.name);
fd.append('total_size', file.size);
fd.append('start_byte', current_byte);
$.ajax(url, {
type: 'post',
data: fd,
success: function (data) {
current_byte = data.next_byte;
upload_id = data.upload_id;
if (data.path) {
success_callback(data.path);
}
else {
percent_complete= Math.round(current_byte/file.size * 100);
if (percent_complete> 100) percent_complete = 100;
progress_callback(percent_complete); // update some UI element to provide feedback to user
upload();
}
}
});
}
};
(原諒任何語法錯誤,只是打字這個把我的頭頂部)
服務器端,我創建了一個新的途徑,以接受文件塊。在首次提交塊時,我根據文件名/大小生成upload_id,並確定是否已從中斷的上載中獲得部分文件。如果是這樣,我回傳我需要的下一個起始字節以及id。如果沒有,我存儲第一塊並傳回ID。
該過程使用額外的塊上載附加部分文件,直到文件大小與原始文件大小相匹配。此時,服務器以文件的臨時路徑進行響應。
然後javascript從窗體中刪除文件輸入,並用一個隱藏的輸入替換它,該輸入的值是從服務器返回的文件路徑,然後發佈窗體。然後,最後在服務器端,我處理移動/重命名文件並將其最終路徑保存到我的模型中。
Phew。
你可以包含你的日誌文件嗎?另外,你在什麼服務器上? – screenmutt
我可以附上日誌,但我不確定這真的會有幫助。在相關時間段內(在上載完成之後,操作執行之前),日誌中絕對沒有任何事情發生。 – Danny
如果它甚至沒有得到你的控制器動作,並且你沒有任何瘋狂的before_filters或around_filters,那麼它必須是你的web服務器或你的中間件。 'rake middleware'中有什麼奇怪的東西? – Taavo