Докачка при аплоаде
Valery Kholodkov
valery+nginxru на grid.net.ru
Сб Ноя 28 23:13:50 MSK 2009
Дмитрий Дедюхин пишет:
>> Да, возможна.
>
> Валерий, я видел у вас в гите экспериментальную ветку с поддержкой дозакачки, но так и не сподобился посмотреть в код.
> Можете в двух словах рассказать, как это реализовано в аплоад-модуле?
> В браузере стандартный input type=file никак не может это реализовать, там нельзя начать загружать файл по смещению. Вы рассчитываете на плагины (Flash или Silverlight)?
Нет, загрузку файлов по частям можно реализовать используя Google Gears
и Blob API. Приблизительно так:
var fileList = {};
function browse() {
var desktop = google.gears.factory.create('beta.desktop');
desktop.openFiles(function(files) {
for (var i=0; i < files.length; i++) {
if(!fileList[files[i].name]) {
fileList[files[i].name] = {
filename: files[i].name,
uploaded: 0,
length: files[i].blob.length,
blob: files[i].blob,
sessionkey: sessionkey(),
};
}
}
$('#upload').html('<a href="#upload" onclick="return
upload();">Upload</a>');
});
}
function upload() {
var chunkLength, chunk;
for(file in mylist) {
if((file.uploaded < file.length && !file.error)) {
chunkLength = min(file.uploaded + CHUNK_BYTES, file.length);
chunk = file.blob.slice(file.uploaded, (chunkLength -
file.uploaded));
sendChunk(file, chunk, file.uploaded, chunkLength,
file.length, file.sessionkey);
}
}
}
function sendChunk(entry, chunk, start, end, total, sessionkey {
var req = google.gears.factory.create('beta.httprequest');
req.open('POST', '/upload');
var headers = {
'Content-Disposition': 'attachment; name="'+sessionkey+'";
filename="'+file+'"',
'Content-Type': 'application/octet-stream',
'Content-Range': 'bytes '+start+'-'+end+'/'+total
};
for(var h in headers) { if(headers.hasOwnProperty(h)) {
req.setRequestHeader(h, headers[x]); } }
req.onreadystatechange = function(){
if(req.readyState == 4 && req.status == 205) {
entry.uploaded = end;
upload();
}
}
req.send(chunk);
}
Далее:
<div>
<a href="#select" onclick="return browse();">Select files</a>
<span id="upload"></span>
</div>
К сожалению, оригинальный клиентский код не мой, поэтому выше приведена
только приблизительная реализация.
На сервере нужен upload module из следующей ветки:
http://github.com/vkholodkov/nginx-upload-module/tree/partial-upload
Директива upload_state_store задает каталог, в котором модуль будет
сохранять состояние загрузки. А именно, список сегментов файла, которые
полностью загружены. Таким образом, загрузки возобновляемы между
перезапусками nginx.
Принцип взаимодействия с бакэндом аналогичный.
Эта ветка экспериментальная, поэтому могут возникнуть всевозможные
неожиданности.
--
Best regards,
Valery Kholodkov
Подробная информация о списке рассылки nginx-ru