YouTube API & JavaScript Upload

Создано Евгений Злобин в июня 26, 2010

Задача: залить видео на ютуб при помощи браузера, html и JS и получить статус запроса и ID загруженного видео.

Никаких серверных технологий не используется. Only native JS.

Задача довольно не тривиальная. И поиск подобной реализации в сети не увенчался успехом. Создано по мотивам AJAX-транспорт Iframe, AjaxFileUpload и YouTube API. Основано на JQuery. Но при желании можно переделать под любой другой фреймворк или вообще без использования оных.

Отмечу, что скрипт уже должен иметь TOKEN и URL, о которых вы можете прочитать в API документации. В данном варианте скрипт разрабатывался для связки:
FLEX(TOKEN, URL)-JS-YOU_TUBE-JS(ID,STATUS)-FLEX

Для начала создадим форму в которой необходимо выбрать файл и нажать кнопку «Загрузить».

 <form name="form" id="form-send" action="" method="POST" enctype="multipart/form-data">
     <input type="hidden" name="yttoken" id="yttoken" value="">
         <input type="hidden" name="yturl" id="yturl" value="">
         <input id="fileToUpload" type="file" size="15" name="fileToUpload" class="input">
     <button class="button" id="buttonUpload">Залить</button>
</form>

И создаём функцию, которая будет всё это дело обрабатывать.

      function ajaxFileUpload(YT_TOKEN, YT_URL) {
        $.ajaxFileUpload ({
            url:YT_URL,
            token:YT_TOKEN,
            secureuri:false,
            fileElementId:'fileToUpload',
            dataType: 'json',
            success: function (data, status) {
               if ( typeof(data.error) != 'undefined' ) {
                 if ( data.error != '' ) {
                   alert(data.error);
                 } else {
                   alert(data.msg);
                 }
               }
            },
            error: function (data, status, e) {
               // myloc = УРЛ редиректа
               myloc = myloc + '';
               var get_pos = myloc.lastIndexOf("?");
               myloc = myloc.substr(get_pos + 1);
               var status_pos = myloc.lastIndexOf("status=");
               var id_pos = myloc.lastIndexOf("id=");
               var err_pos = myloc.lastIndexOf("error=");

               ret_status = id_pos == -1 ?
               myloc.substr(7,err_pos-8) : myloc.substr(7,id_pos-8);
               ret_id = id_pos == -1 ?
               myloc.substr(err_pos+6) : myloc.substr(id_pos+3);
               alert(ret_status + ',' + ret_id);
            }
          }
        )
        return false;
      }

Навешиваем на кнопку загрузки выполнение вышеприведённой функции

    $('#buttonUpload').click(function() {
        return ajaxFileUpload($('#yttoken').attr('value'),$('#yturl').attr('value'));
    });

Суть работы скрипта такова – юзер выбирает файл на своём компьютере, затем нажимает кнопку «загрузить». И вызывается функция, приведенная выше. Которая выполняет следующие действия – создаётся iframe и форма при помощи которой мы будем отсылать данные на сервер YouTube

  createUploadIframe: function(id, uri) {
      var frameId = 'jUploadFrame' + id;
      if ( window.ActiveXObject ) {
            var io = document.createElement('<iframe id="' + frameId + '" name="' + frameId + '" />');
            if ( typeof uri== 'boolean' ){
                  io.src = 'javascript:false';
            } else if ( typeof uri == 'string' ) {
                  io.src = uri;
            }
      } else {
            var io = document.createElement('iframe');
            io.id = frameId;
            io.name = frameId;
      }

      io.style.position = 'absolute';
      io.style.top = '-1000px';
      io.style.left = '-1000px';
      document.body.appendChild(io);
      return io
},

createUploadForm: function(id, fileElementId, YT_URL, YT_TOKEN) {
      var formId = 'jUploadForm' + id;
      var fileId = 'jUploadFile' + id;
      var form = $('<form  action="' + YT_URL + '" method="POST" name="' + formId +
      '" id="' + formId + '" enctype="multipart/form-data"> <input type="hidden"
      name="token" value="' + YT_TOKEN + '"/></form>');
      var oldElement = $('#' + fileElementId);
      var newElement = $(oldElement).clone();
      $(oldElement).attr('id', fileId);
      $(oldElement).before(newElement);
      $(oldElement).appendTo(form);
      $(form).css('position', 'absolute');
      $(form).css('top', '-1200px');
      $(form).css('left', '-1200px');
      $(form).appendTo('body');
      return form;
},

Ну и соответственно функции, которые осуществляют Ajax транспорт и получают данные


ajaxFileUpload: function(s) {
    s = jQuery.extend({}, jQuery.ajaxSettings, s);
    var id = new Date().getTime()
    var form = jQuery.createUploadForm(id, s.fileElementId, s.url, s.token);
    var io = jQuery.createUploadIframe(id, s.secureuri);
    var frameId = 'jUploadFrame' + id;
    var formId = 'jUploadForm' + id;
    if ( s.global && ! jQuery.active++ ) {
        jQuery.event.trigger( "ajaxStart" );
    }
    var requestDone = false;
    var xml = {}
    if ( s.global )
        jQuery.event.trigger("ajaxSend", [xml, s]);
    // Ждём ответа
    var uploadCallback = function(isTimeout) {
    var io = document.getElementById(frameId);
    try {
        if( io.contentWindow ) {
            xml.responseText = io.contentWindow.document.body?io.contentWindow.document.body.innerHTML:null;
            xml.responseXML = io.contentWindow.document.XMLDocument?io.contentWindow.document.XMLDocument:io.contentWindow.document;
        } else if ( io.contentDocument ) {
            xml.responseText = io.contentDocument.document.body?io.contentDocument.document.body.innerHTML:null;
            xml.responseXML = io.contentDocument.document.XMLDocument?io.contentDocument.document.XMLDocument:io.contentDocument.document;
        }
    } catch(e) {
        myloc = window.frames[frameId].location;
        jQuery.handleError(s, xml, null, e);
        //alert('err1');
    }
    if ( xml || isTimeout == "timeout" ) {
        requestDone = true;
        var status;
        try {
            status = isTimeout != "timeout" ? "success" : "error";
            if ( status != "error" ) {
                var data = jQuery.uploadHttpData( xml, s.dataType );
                if ( s.success )
                    s.success( data, status );
                if( s.global )
                    jQuery.event.trigger( "ajaxSuccess", [xml, s] );
            } else {
                jQuery.handleError(s, xml, status);
            }
        } catch(e) {
        status = "error";
        myloc = window.frames[frameId].location;
        //alert('err3');
        jQuery.handleError(s, xml, status, e);
    }
    // Запрос завершен
    if( s.global ) {
        jQuery.event.trigger( "ajaxComplete", [xml, s] );
    }
    if ( s.global && ! --jQuery.active ) {
        jQuery.event.trigger( "ajaxStop" );
    }
    // результаты
    if ( s.complete ) {
        s.complete(xml, status);
    }
    jQuery(io).unbind()
    setTimeout(function(){
       try {
            $(io).remove();
            $(form).remove();
        } catch(e) {
            myloc = window.frames[frameId].location;
            jQuery.handleError(s, xml, null, e);
            //alert('err4');
        }
    }, 100)
    xml = null
}}

if ( s.timeout > 0 ) {
    setTimeout(function(){
        if( !requestDone ) uploadCallback( "timeout" );
    }, s.timeout);
}

try {
    // var io = $('#' + frameId);
    var form = $('#' + formId);
    $(form).attr('action', s.url);
    $(form).attr('method', 'POST');
    $(form).attr('target', frameId);
    if ( form.encoding ) {
        form.encoding = 'multipart/form-data';
    } else {
        form.enctype = 'multipart/form-data';
    }
    $(form).submit();
    } catch(e) {
        jQuery.handleError(s, xml, null, e);
    }
    if ( window.attachEvent ) {
        document.getElementById(frameId).attachEvent('onload', uploadCallback);
    } else {
        document.getElementById(frameId).addEventListener('load', uploadCallback, false);
    }
return {abort: function (){}};
},
uploadHttpData: function( r, type ) {
    var data = !type;
    data = type == "xml" || data ? r.responseXML : r.responseText;
    if ( type == "script" )
        jQuery.globalEval( data );
    if ( type == "json" )
        eval( "data = " + data );
    if ( type == "html" )
        jQuery("<div>").html(data).evalScripts();
    //alert($('param', data).each(function(){alert($(this).attr('value'));}));
    return data;
}

В итоге двое суток работы и задача решена ;) Ну и прикрепляю исходные коды скрипта. Скачать

Может быть Вам это интересно?

36 отв. в “YouTube API & JavaScript Upload”

  1. Неплохо придумано и главное полезно, пригодится. Я думаю оценят по достоинству.

  2. mafia2world

    Жесть. Учусь потихоньку программированию. Но пока для меня это сложно.

  3. Незнаю полезно ли, хотя для кого как…мне дак оно вообще не нужно

  4. Дмитрий

    Да, наворочено…. но надо пробовать, а-то у других есть и мне охота…

  5. Евгений

    Спасибо большое. Мне очень помогло. А то я долго мучался!!!

  6. Конечно круто, но слишком грузно моно и по проще сделать ;)

  7. Работа неплохая. Только где использовать данный скрипт не сильно понятно.

  8. Андрей

    Огромное спасибо за данный скриптик, какраз пригодится для нового сайта!

  9. Рубль

    Только начал изучать но я не сказал бы что это легко.

  10. Полезно однозначно. А если кому бесполезно – так для общего развития пригодиться, а то рискуем в рядовых потребителей деградировать, на радость буржуям.

  11. Спасибо за полезный скрипт. нужно будет использовать для своих видео файлов.

  12. Евгений Злобин

    lyrics, да слижком уж это узко специализированно. Просто нам понадобилась такая реализация для одного из виджетов на Flex.

  13. Небезопасно все это…

  14. dominicanseo

    Зафига открытый код выкладывать?

  15. полезно, очень даже.

  16. Очень круто. Вопрос рождается сам с собой- «Зачем??» Если есть по дефолту такая функция на ютубе?! Или это просто фичя на хостинг?

  17. Андрей

    Создатель достоин одного слова СПАСИБО !!!

  18. Евгений Злобин

    SpauN, это было написано для одного нашего сайта.

  19. создатель наверно гений, или просто знает свою работу! чтобы такой скрипт написать нужна голова, кароче спасибо

  20. Мориц

    голова нужна оОООо! :)
    столько «спасибо».. только я ума не приложу, это чтобы грузить видео на трубу через свой сайт? :/

  21. Алексей

    Вроде нормуль,но сильно грузит….
    Мб попроще сделаю,на досуге

  22. Тем не менее постоянно у них испытываю проблемы с заливкой видео

  23. Сергей

    Спасибо скрипт очень полезный и мне очень помог, не всегда удобно грузить по дефолту как уже было сказано, а с помощью скрипта очень удобно!

  24. Что-то не работает, передаю токен через google AuthSubRequest. После закачки выдает только алерт с именем домена.

  25. Евгений Злобин

    Geby, ну а само видео то вообще закачивается? Тут есть ещё один подводный камень, о котором я узнал уже позже. Нужно, чтобы этот скрипт обязательно выполнять на каком-либо сервере, т.е. если запускаете со своего компа, то нужно запускать, например с http://localhost/ Видимо это как-то связано с получением HTTP_REFERER

  26. Запускал сразу на хосте. Возможео неверно оформляю запрос. Может есть рабочий пример?

  27. Я считаю полезно, ну как по мне так пригодилось

  28. Кто-нибудь пробовал адаптировать его под blip.tv? а то на ютубе ограничения по размеру/времени..

  29. Евгений Злобин

    Geby, напишите мне в скайп creastar-group

  30. порно трекер

    интересный код. спасибо

  31. Про Zend_Gdata слыхали? Уже все давно написано :) http://code.google.com/intl/en/apis/youtube/2.0/developers_guide_php.html

  32. Евгений Злобин

    вообще-то вы описываете серверную часть. У меня идет описание работы без оной.

  33. Аянами Рей

    Отлично, надо будет использовать где-то.

  34. Дмитрий

    Есть ли какие то варианты отображения здесь progress bar, процента загрузки видео?

  35. Евгений Злобин

    Дмитрий, видел что в браузере это отображается, но вот возможно ли это как-то перехватить даже не знаю.

  36. Дмитрий

    Эта штука не работает в опере?

Оставить ответ