887 messaggi dal 21 marzo 2008
Ciao a tutt
qualche settimana fa avevo aperto una discussione sull'upload di video su youtube da un pannello di controllo utilizzando le api. Per caricare i video utilizzavo uplodify e quando provavo a caricare file di grandi dimensioni(avevo fatto test con file di 78 e 110 mega), uplodify mi restituiva errore.

Non so spiegarmi come, ma lo stesso codice copiato in un'altro progetto ora funziona.

Ora ho questo problema: seleziono il file di grandi dimensioni, carico il file con uplodify, il file viene caricato su youtube e la mia applicazione rimane in attesa che youtube restituisca il videoID assegnato al video. Il problema è che dopo un pò di tempo l'esecuzione del codice si blocca e non mi restituisce il codice associato al video, ma il video è presente su youtube. Dato che devo salvare su un database il codice. questo è un problema.
Perchè accade questo?
Come posso caricare un file di grandi dimensioni senza utilizzare uplodify?
A qualcuno è mai capitato di carica un file di grandi dimensioni con le api di youtube?

Quì trovate un pò di codice:

#MASTERPAGE#
<form id="frmMaster" method="post" runat="server" enctype="multipart/form-data">
        <asp:ToolkitScriptManager ID="smAdmin" AsyncPostBackTimeout="999999" EnableScriptGlobalization="true" EnableScriptLocalization="true" EnablePageMethods="true" runat="server"></asp:ToolkitScriptManager>

#VIDEO.ASPX#
<!-- Video -->
    <script type="text/javascript">
        $(function () {
            $("#fuVideo").uploadify({
                'fileSizeLimit' : '0',
                'swf': '/Scripts/Uploadify/uploadify.swf',
                'uploader': '/Handler/FileUpload.ashx',                
                'fileTypeDesc' : 'Video Files',
                'fileTypeExts' : '<%= YouTube.VIDEO_FORMAT %>',
                'queueSizeLimit' : 1,
                'removeTimeout' : 1,
                'multi': false,
                'auto': false,                   
                'successTimeout': 36000,
                'onUploadSuccess' : function(file, data, response) {
                    $('#loading').hide();
                    if(response)
                    {
                        var obj = jQuery.parseJSON(data);                        
                        if(obj.msg_error == '')
                        {
                            $('#<%= hdYouTube.ClientID %>').val('[{"Key" : "VideoId", "Value" : "' + obj.id_item + '" },{"Key" : "Image", "Value" : "' + obj.filename + '"}]');
                            var operazione = $('#<%= hdOperazione.ClientID %>').val(); 
                            switch(operazione)
                            {
                                case "applica":
                                    $('#<%= btnApplica.ClientID %>').click();
                                    break;

                                case "salva":
                                    $('#<%= btnSalva.ClientID %>').click();
                                    break;
                            }
                        }
                        else
                        {
                            $('#loading').hide();
                            alert(obj.msg_error);
                            e.preventDefault();
                        }
                    }
                    else
                    {
                        $('#loading').hide();
                        alert('<%= Messaggi.ERR_UPLOAD_VIDEO %>');
                        e.preventDefault();
                    }
                },
                'onUploadError' : function(file, errorCode, errorMsg, errorString) {
                    $('#loading').hide();
                    alert('<%= Messaggi.ERR_UPLOAD_VIDEO %>');
                    e.preventDefault();
                },
                'onUploadStart' : function(file) {
                    $('#fuVideo').uploadify('settings','formData',{
                        'type' : 'video_news',                         
                        'title' : $('#<%= txtTitolo.ClientID %>').val(),
                        'title_old' : $('#<%= hdTitleOld.ClientID %>').val(),
                        'category' : $('#<%= ddlCategoria.ClientID %>').val(),  
                        'description' : $('#<%= txtDescription.ClientID %>').val(),
                        'keywords' : $('#<%=txtKeywords.ClientID %>').val()
                    });
                }
            });          
        });
    </script>
    <!-- fine Video -->


#FILEUPLOAD.ASHX#
public void ProcessRequest(HttpContext context)
    {
        context.Response.ContentType = "text/plain";
        context.Response.Expires = -1;
        
        string type = context.Request["type"];
        string id = context.Request["id"];
        string result = string.Empty;
        if (context.Request.Files.Count == 0)
        {
            context.Response.ContentType = "text/plain";
            context.Response.Write("{\"msg_error\":\"" + Messaggi.ERR_NO_FILE + "\"}");
        }
        else
        {
            HttpPostedFile uploadedfile = context.Request.Files["Filedata"];

            if (uploadedfile != null && uploadedfile.ContentLength > 0)
            {
                string FileName = uploadedfile.FileName;
                string FileType = uploadedfile.ContentType;
                int FileSize = uploadedfile.ContentLength;

                string id_item = "0";
                string name = string.Empty;
                string filename = string.Empty;
                string link = string.Empty;
                string error = string.Empty;
                                
                List<string> msg_error = new List<string>();
                List<string> param = new List<string>();

                LogRequest(FileName + ", " + FileType + ", " + FileSize);

                switch (type)
                {                     
                    case "video_news":
                        string _title = context.Request["title"];
                        string _title_old = context.Request["title_old"];
                        string _category = context.Request["category"];                        
                        _category = _category;
                        string _description = context.Request["description"];
                        string _keywords = context.Request["keywords"];                       

                        tipoYouTubeVideo _video = new tipoYouTubeVideo();                        
                        _video.Title = _title;
                        _video.TitleOld = _title_old;
                        _video.Category = _category;
                        _video.Description = _description;
                        _video.Keywords = _keywords;                        
                        _video.Upload = uploadedfile;
                        if (News.salvaVideo(_video, out msg_error))
                        {
                            id_item = _video.VideoId;
                            name = _title;
                            filename = _video.Image;
                            link = _video.Watch;
                        }
                        else
                        {
                            msg_error.ForEach(item => error += (!string.IsNullOrEmpty(error) ? "\r\n" : string.Empty) + item);
                        }
                        break;

                    default:
                        break;
                }

                if (id_item != "0" && id_item != string.Empty)
                    result = "{\"id_item\":\"" + id_item + "\",\"name\":\"" + name + "\",\"filename\":\"" + filename + "\",\"link\":\"" + link + "\",\"msg_error\":\"" + error + "\"}";
                else
                    result = "{\"id_item\":\"\",\"name\":\"\",\"filename\":\"\",\"link\":\"\",\"msg_error\":\"" + error + "\"}";
            }
            else
            {
                result = "{\"msg_error\":\"" + Messaggi.ERR_DESC_ZERO_LENGTH_FILE + "\"}";
            }
            context.Response.ContentType = "text/plain";
            context.Response.Write(result);
        }
    }


#YOUTUBE.CS#
public static bool salvaVideo(tipoYouTubeVideo video, out List<string> msg_error)
    {
        msg_error = new List<string>();

        try
        {
            bool errore = false;
            string filename = video.Upload.FileName;
            string FileType = video.Upload.ContentType;
            string videoname = Utility.PERCORSO_FISICO(VIDEO_TEMP_FOLDER + video.Codice + "_" + Formattazione.EliminaCaratteriSpeciali(filename, "_"));


            if (!errore)
            {                
                video.Upload.SaveAs(videoname);

                //Autenticazione
                YouTubeRequest request = new YouTubeRequest(settings);                
                ((GDataRequestFactory)request.Service.RequestFactory).Timeout = 9999999;

                Video newVideo = new Video();
                newVideo.Title = Formattazione.SottoStringa(Formattazione.FormatString(System.Web.HttpUtility.HtmlDecode(video.Title)), TITLE_MAX_CHARACTER, false);
                newVideo.Tags.Add(new MediaCategory(video.Category, YouTubeNameTable.CategorySchema));
                newVideo.Keywords = System.Web.HttpUtility.HtmlDecode(video.Keywords);
                newVideo.Description = Formattazione.SottoStringa(Formattazione.FormatString(System.Web.HttpUtility.HtmlDecode(video.Description)), DESCRIPTION_MAX_CHARACTER, false);
                newVideo.YouTubeEntry.Private = true;
                newVideo.Tags.Add(new MediaCategory(video.DeveloperTag, YouTubeNameTable.DeveloperTagSchema));
                newVideo.YouTubeEntry.setYouTubeExtension("location", "Andria, BT");
                newVideo.YouTubeEntry.MediaSource = new MediaFileSource(videoname, FileType);
                Video createdVideo = request.Upload(newVideo);

                if (createdVideo != null)
                {
                    video.VideoId  = createdVideo.VideoId;
                    video.Image = createdVideo.Thumbnails[0].Url;
                }

                //Elimino il video il locale
                IO.DeleteFile(videoname);

                return true;
            }
            else
            {
                return false;
            }
        }
        catch (Exception ex)
        {
            msg_error.Add(Messaggi.ERR_UPLOAD_VIDEO);

            if (!string.IsNullOrEmpty(video.VideoId)) YouTube.Elimina(video.VideoId);

            return false;
        }
    }



Esegue Video createdVideo = request.Upload(newVideo);, carica il video su youtube, ma poi non va avanti.

#WEB.CONFIG#
<?xml version="1.0"?>
<configuration>
  <configSections>
    <sectionGroup name="ajaxNet">
      <section name="ajaxSettings" type="AjaxPro.AjaxSettingsSectionHandler,AjaxPro.2" requirePermission="false" restartOnExternalChanges="true"/>
    </sectionGroup>
  </configSections>
  <appSettings>    
  </appSettings>
  <connectionStrings>   
  </connectionStrings>
  <system.web>
    <globalization enableClientBasedCulture="true" culture="auto" uiCulture="auto:it-IT" fileEncoding="utf-8" requestEncoding="utf-8" responseEncoding="utf-8" responseHeaderEncoding="utf-8" enableBestFitResponseEncoding="true"/>
    <pages enableEventValidation="false" viewStateEncryptionMode="Never" enableViewStateMac="false" controlRenderingCompatibilityVersion="3.5" clientIDMode="AutoID" validateRequest="false">
      <controls>
        <add tagPrefix="CKEditor" namespace="CKEditor.NET" assembly="CKEditor.NET"/>
      </controls>
    </pages>
    <compilation debug="true" targetFramework="4.0">
      <assemblies>
        <add assembly="System.Design, Version=4.0.0.0, Culture=neutral, PublicKeyToken=B03F5F7F11D50A3A"/>
        <add assembly="System.Data.Entity, Version=4.0.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089"/>
        <add assembly="System.Data.Linq, Version=4.0.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089"/>
        <add assembly="System.Data.Services.Client, Version=4.0.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089"/>
        <add assembly="System.Data.Services.Design, Version=4.0.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089"/>
        <add assembly="System.Web.Abstractions, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/>
        <add assembly="System.Web.Extensions.Design, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/>
        <add assembly="System.Web.RegularExpressions, Version=4.0.0.0, Culture=neutral, PublicKeyToken=B03F5F7F11D50A3A"/>
        <add assembly="WindowsBase, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/>
        <add assembly="System.Web.Routing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/>
      </assemblies>
    </compilation>
    <authentication mode="Forms">
      <forms name=".ASPXAUTH" loginUrl="~/Admin/login.aspx" protection="Validation" timeout="999999" defaultUrl="~/Admin/default.aspx"/>
    </authentication>
    <customErrors mode="RemoteOnly" defaultRedirect="GenericErrorPage.aspx">
      <error statusCode="403" redirect="NoAccess.aspx"/>
      <error statusCode="404" redirect="FileNotFound.aspx"/>
    </customErrors>
    <sessionState mode="InProc"/>
    <httpRuntime maxRequestLength="2097151" requestLengthDiskThreshold="999999" executionTimeout="999999" enableHeaderChecking="false" enable="true"/>    
  </system.web>
  <system.webServer>
    <modules runAllManagedModulesForAllRequests="true"/>
  </system.webServer>
  <location path="ajaxpro">
    <system.web>
      <httpHandlers>
        <add verb="*" path="*.ashx" type="AjaxPro.AjaxHandlerFactory,AjaxPro.2"/>
      </httpHandlers>
    </system.web>
  </location>
</configuration>


Grazie mille
11.886 messaggi dal 09 febbraio 2002
Contributi
ciao,
caricare file così grossi è sempre una difficoltà e la soluzione più "naturale" sarebbe quella di farli trasferire all'utente via FTP.
Comunque, guarda il valore di maxRequestLength, sei stato costretto ad impostarlo a 2GB ma il server non riuscirà a gestire un file di quelle dimensioni in memoria. E se la connessione dell'utente dovesse interromprsi per un momento, sarebbe costretto a ricaricare il file da capo?

La prima necessità è quella di fare in modo che il file venga uploadato in piccoli pezzi, o chunks, così saranno più gestibili dal server e se anche la connessione dovesse interrompersi per un attimo, l'upload riprenderebbe dall'ultimo chunk.

Uploadify, da quanto leggo qui, non ha ancora le funzioni di chunking e resuming che sono supportate dalla File API di HTML5.

Questo plugin però ne ha il supporto.
https://github.com/blueimp/jQuery-File-Upload

Ora c'è un problema da risolvere. Se il server riceve il file in piccoli chunks, dovrà salvarli uno ad uno, man mano che gli arrivano e ricomporli al termine in un unico file. Cosa che si può fare così.

Il plugin che ti ho linkato non ha un esempio che usa un HttpHandler, quindi probabilmente dovrai scriverlo tu, dopo aver esaminato quali variabili ti vengono fornite col post. Riceverai di sicuro i dati binari e poi l'ordinale del chunk e il numero di chunks totali.

Quando il video è stato caricato con successo, io non aspetterei altro e comunicherei subito all'utente che la sua richiesta di upload su youtube è stata messa in coda.
Farei così perché non posso avere la garanzia che l'API di YouTube, in quel momento, sia funzionante. Inoltre farei attendere altri minuti preziosi all'utente, che magari ha altri video da caricare.

Dunque realizzerei un servizio per windows (se hai il controllo del server) o comunque lancerei un Task da Asp.Net che mi legga dal database i dati del primo video in coda ed inizi ad inviarlo a YouTube. Se l'operazione avrà successo, aggiornerà l'ID, altrimenti riproverà più tardi.
L'interfaccia grafica dovrà comunque informare l'utente sui video che ha in coda e su quelli che sono già stati uploadati.

Io non conosco la API di youtube, vedi se magari ti consente per prima cosa di caricare le informazioni testuali (titolo, descrizione), in modo da avere subito l'ID della nuova entry. Successivamente, carica il video e al termine rendilo visibile pubblicamente.

ciao
Modificato da BrightSoul il 25 maggio 2013 18.24 -

Enjoy learning and just keep making
887 messaggi dal 21 marzo 2008
Ciao e grazie per l'aiuto
Domanda: è possibile utilizzare l'ftp in un sito web? Mi spiego meglio: è possibile dare la possibilità, da pannello di controllo, all'utente di selezionare il file e quando clicca su carica far partire ftp?
Grazie
11.886 messaggi dal 09 febbraio 2002
Contributi
ciao, prego!

Nonostante l'FTP sia il protocollo più idoneo per trasferire file di grosse dimensioni, sei sicuro di non voler provare l'altra strada prima?

Gemini78 ha scritto:

è possibile utilizzare l'ftp in un sito web?

No, infatti la difficoltà per l'utente è che deve appunto uscire dalla pagina per usare un client FTP.
Nella pagina potresti mettere un link a ftp://nomeutente:password@ftp.sito.it/ ma questo verrebbe gestito dal browser stesso che presenterebbe all'utente un listato in sola lettura dei file presenti nello spazio FTP. Se hai accesso diretto al PC dell'utente (cioè se la tua è un'applicazione che gira in intranet) potresti legare il protocollo ftp:// al client FTP.
In questo modo, quando l'utente clicca un link che inizia con ftp:// gli si aprirà direttamente il client FTP.

Per causare la minima interruzione all'utente, dovresti separare i momenti di upload dei file e di inserimento dati. Fai in modo l'utente abbia la facoltà di caricare più file alla volta, in modo che poi ne abbia abbastanza da caricare su YouTube usando la tua applicazione. Ad esempio potresti realizzarla in questo modo:
  • Una pagina di elenco mostra tutti i file presenti nello spazio FTP. Se non ci sono files, verrà visualizzato una avviso: "Collegati allo spazio FTP su ftp.sito.it con queste credenziali (utente e password) per iniziare la procedura di caricamento su YouTube.
  • A quel punto l'utente aprirà il client FTP e sceglierà di caricare uno o più filmati alla volta, se lo preferisce.
  • Terminato l'upload, tornerà nella pagina web di elenco e là troverà i nomi dei file che ha appena caricato. Cliccando una delle voci nella lista, potrà inserire il titolo, la descrizione e gli altri dati. Alla pressione del tasto "Carica su YouTube", il file verrà spostato dallo spazio FTP e inserito in un'altra cartella, così da evitare eventuali intereferenze da parte dell'utente via client FTP.
    La procedura di upload verrà dunque accodata e l'utente sarà reindirizzato alla pagina di elenco da cui potrà selezionare un altro file.
  • Dalla stessa pagina di elenco i file spariranno man mano che le procedure di upload su YouTube si completano correttamente.


Però prova anche l'altra soluzione. Investendoci un po' di tempo penso che si riesca a metterla in pratica.

ciao!
Modificato da BrightSoul il 30 maggio 2013 21.16 -

Enjoy learning and just keep making
887 messaggi dal 21 marzo 2008
Ciao
grazie ancora per l'aiuto. Non ho scartato la prima soluzione proposta, solo che non mi è molto chiara e dovrei studiare un pò, ma ho tempi strettissimi e cerco una soluzione più veloce con del codice di esempio già pronto.
Non credo che mai a nessuno sia capitato di dover creare un pannello per far l'upload, in questo caso su youtube, di video di grandi dimensioni.
ancora grazie
11.886 messaggi dal 09 febbraio 2002
Contributi
ciao!

Gemini78 ha scritto:

Non credo che mai a nessuno sia capitato di dover creare un pannello per far l'upload, in questo caso su youtube, di video di grandi dimensioni.

E' che probabilmente per altri il problema non si pone: postano il video direttamente alla API di YouTube senza passare per il proprio server web.

Come si legge nella documentazione della loro API, l'upload di un video, se fatto da browser, è un'operazione che si può svolgere in due richieste: prima l'invio dei metadati (titolo, descrizione, ecc..) e poi l'invio del video vero e proprio. La prima richiesta la posti al tuo server, in modo che possa salvare una copia dei dati su database, ma per la seconda puoi postare i dati binari direttamente a YouTube, ad un URL speciale che ti è stato fornito come risposta alla prima richiesta.

Quindi chiediti se è realmente necessario che il video sia postato prima al tuo server. Magari sì, perché vuoi tenerne una copia o perché la banda in upload dell'utente lo terrebbe incollato alla pagina per troppo tempo. Meglio, a quel punto, farlo postare direttamente al server che si trova in rete locale, ammesso che la tua applicazione giri in una intranet.

Se scegli per questa seconda strada puoi usare il plugin di jQuery che ti ho segnalato. In realtà l'HttpHandler per ASP.NET esiste eccome, eccolo qui, è stato sviluppato da tale Shannon Whitley.
https://github.com/swhitley/jQuery-File-Upload/blob/master/server/dotnet/UploadHandler.cs

Non so dirti quale delle due soluzioni sia più veloce da mettere in pratica nel tuo caso. Dipende dal punto in cui si trova la tua applicazione in questo momento. Forse la seconda è più veloce dato che stai già gestendo l'upload su YouTube lato server. Devi "solo" configurare il plugin di jQuery per l'upload.

ciao

Enjoy learning and just keep making
887 messaggi dal 21 marzo 2008
Grazie
proverò con la prima soluzione

Torna al forum | Feed RSS

ASPItalia.com non è responsabile per il contenuto dei messaggi presenti su questo servizio, non avendo nessun controllo sui messaggi postati nei propri forum, che rappresentano l'espressione del pensiero degli autori.