2012-07-18 10 views
5

Sto utilizzando heroku per ospitare un'applicazione Web con l'obiettivo principale di ospitare video. I video sono ospitati da vimeo pro e sto utilizzando lo vimeo gem by matthooks per gestire il processo di caricamento. Il caricamento funziona per file di piccole dimensioni, ma non per quelli più grandi (~ 50mb, ad esempio).Come caricare file di grandi dimensioni su Heroku (in particolare video)

Uno sguardo ai registri di heroku mostra che sto ricevendo l'errore http 413, che sta per "Richiesta Entità troppo grande". Credo che questo potrebbe avere a che fare con un limite che heroku pone sui file caricati (maggiore di 30mb, according to this webpage). Il problema però è che qualsiasi informazione che posso trovare sull'argomento sembra essere obsoleta e in conflitto (come questa pagina che claims there is no size limit). Non sono riuscito a trovare nulla sul sito di heroku a riguardo.

Ho cercato su google e ho trovato alcune pagine piuttosto rilevanti (one e two), ma nessuna soluzione ha funzionato per me. La maggior parte delle pagine che ho trovato riguardano il caricamento di file di grandi dimensioni su amazon s3, che è diverso da quello che sto cercando di fare.

Ecco la relativa uscita dei tronchi:

2012-07-18T05:13:31+00:00 heroku[nginx]: 152.3.68.6 - - [18/Jul/2012:05:13:31 +0000] 
    "POST /videos HTTP/1.1" 413 192 "http://neoteach.com/components/19" "Mozilla/5.0 
    (Macintosh; Intel Mac OS X 10.7; rv:13.0) Gecko/20100101 Firefox/13.0.1" neoteach.com 

Non ci sono altri errori nei log. Questo è l'unico output che appare quando provo a caricare un video troppo grande. Ciò significa che questo non è un errore di timeout o un problema con il superamento della memoria assegnata per dyno.

Does heroku pone davvero un limite alle dimensioni di upload? Se è così, c'è un modo per cambiare questo limite? Si noti che i file stessi non vengono memorizzati sui server di heroku, vengono semplicemente trasmessi ai server di vimeo.

Se il problema non è limitato alle dimensioni di caricamento, qualcuno ha un'idea di cos'altro potrebbe andare storto?

Grazie mille!

+0

Per quanto ne so, non esiste un modo. Ho dovuto caricare direttamente su S3. Potresti riuscire a trovare un modo per passare i video direttamente a Vimeo, ma l'unico risultato che ho trovato non è stato molto incoraggiante: http://vimeo.com/forums/topic:28113 – Qsario

+0

Degno di nota, ho appena provato caricamento di un file di 8,5 MB nella mia app di Heroku, che ha richiesto 3 minuti e 15 secondi (sì, ho DSL). Ho 'web: gunicorn -t 60 -k" eventlet "-w 3 myapp.wsgi: application' nel mio' Procfile'. In altre parole, ho aumentato il timeout a 60 secondi e la mia app consentirà un caricamento di più di 3 minuti. Non sono sicuro del motivo per questo, ma ha qualcosa a che fare con il mio Dyno che consente connessioni simultanee. – orokusaki

risposta

4

Aggiornamento:

OP qui. Non sono ancora sicuro del motivo per cui ho ricevuto questo particolare errore 413, ma sono riuscito a trovare una soluzione che funzioni utilizzando la gemma s3_swf_upload. L'implementazione coinvolge il flash, che non è l'ideale, ma è stata l'unica soluzione (su 3 o 4 che ho provato) che avrei potuto ottenere lavorando.

Come ha fatto notare Neil (grazie a Neil!), L'errore che avrei dovuto ottenere è "H12 - Request timeout". E ho finito per incappare in questo errore dopo ripetute prove.Il problema si verifica quando si tenta di caricare file di grandi dimensioni sul server heroku dal controller (utilizzando un dyno Web), poiché il server impiega troppo tempo a rispondere alla richiesta di post.

L'approccio corretto è inviare il file direttamente a s3 senza passare attraverso heroku.

Ecco una panoramica di alto livello del mio approccio:

  1. Utilizzare la gemma s3_swf_upload per la fornitura di un modulo di upload diretto a S3.
  2. Rileva quando il file ha terminato il caricamento con la funzione di callback javascript fornita nella gemma.
  3. Utilizzando javascript, invia un messaggio postale ai binari per far sapere al tuo server che il caricamento del file è terminato.
  4. Il controller che risponde al post javascript fa due cose: (a) assegna un attributo s3_key all'oggetto video (reso disponibile come parametro nel modulo). (b) avvia un'attività in background utilizzando la gemma delayed_job.
  5. L'attività in background recupera il file da s3. Ho usato la gemma aws-sdk per realizzare questo, perché era già inclusa in s3_swf_upload. Si noti che questo è nettamente diverso dalla gemma aws-s3 (in effetti sono in conflitto tra loro).
  6. Dopo che il file è stato recuperato da s3, ho usato la gemma vimeo per caricarla su vimeo (sempre in background).

L'implementazione sopra funziona, ma non è perfetto. Per i file che hanno dimensioni prossime a 500 MB, continuerai a riscontrare errori R14 nei tuoi dynos di lavoro. Ciò si verifica perché heroku assegna solo 512 MB di memoria per dyno, quindi non è possibile caricare l'intero file in memoria in una sola volta. Il modo per aggirare questo problema è implementare una sorta di chunking nel passaggio finale, in cui recuperi il file da s3 e lo carichi in vimeo pezzo per pezzo. Sto ancora lavorando a questa parte, e mi piacerebbe sentire tutti i suggerimenti che potresti avere.

Speriamo che questo possa aiutare qualcuno. Sentiti libero di farmi qualsiasi domanda. Come ho detto, la mia soluzione non è perfetta quindi sentiti libero di aggiungere la tua risposta se pensi che potrebbe essere migliore.

+0

Guarda "Carrierwave" con "Fog" e "CarrierwaveDirect" – Narfanator

+0

È utile, grazie! –

2

Il tuo problema più grande non è la dimensione dei file qui, ma il fatto che ti aspetti che l'utente carichi file di grandi dimensioni su Heroku e poi li faccia passare. Il problema qui è che tutte le richieste sulla piattaforma Heroku devono restituire il primo byte entro 30 secondi, il che nel tuo caso è molto improbabile.

Pertanto, è necessario verificare che gli utenti caricino direttamente su S3/Vimeo/ovunque e quindi collegano i dati dell'applicazione a tali risorse caricate.

Se si utilizza Ruby, la gemma diretta dell'onda portante potrebbe valerne la pena. In mancanza ci sono servizi di terze parti che ti permettono di farlo tramite un codice che puoi inserire nella pagina, ma questi hanno un costo allegato.

+0

Grazie Neil, il problema descritto sopra non sembra essere un timeout. Non c'è "H12 - Request timeout" nei log.Capisco tuttavia che il timeout è un grosso rischio con i grandi caricamenti di file, quindi esaminerò i caricamenti diretti. Forse questo risolverà anche il problema sopra. – stephenalexbrowne

+0

Dovrebbe. Immagino che tu stia testando su una connessione decente finora. –

+0

È solo quando una connessione è inattiva per 30 secondi che è scaduta. –

2

Penso che l'opzione migliore qui è infatti quella di caricare direttamente su S3. È molto più economico e molto più sicuro che permettere agli utenti di caricare file sul proprio server (o Heroku in questo caso). È anche un modello ben collaudato utilizzato da molte piattaforme di hosting video (so che lo farò).

Scopri i jQuery caricare plug-in, che consente il caricamento diretto di S3: https://github.com/blueimp/jQuery-File-Upload

controllare anche le Railscasts intorno a questo argomento: # 381 e # 383.