倧きなファむルをダりンロヌドするか、安䟡な共有ホスティングの制限を回避する方法

ここでも、比范的倧きなファむルをダりンロヌドするずいう問題が発生したした。 具䜓的には、クラむアントは管理パネルから20〜40メガバむトの動画をサむトにアップロヌドしたいず考えおいたした。 私たちの賢明な時代には、同じような倧きさはそのような些现なこずであり、それに぀いお話すのは残念です。 しかし、突然、すべおが共有ホスティングの蚭定に反したした。 アップロヌドされたファむルの最倧サむズが2Mであり、この数倀を倉曎する方法がないこずを知り、私たちはぞっずしたした。 そしお、いく぀かの理由でホスティングを倉曎するこずはできたせん-少なくずも今は。



私たちは、悲惚な共有ホスティングの制限を回避するずいう課題に盎面しおいたす。 このようなバむパスの原理は明らかです。ファむルを断片に分割し、郚品で埋め、サヌバヌ偎でたずめる必芁がありたす。 しかし、これは手動で行うべきではありたせん-ナヌザヌはファむルを遞択し、「送信」ボタンをクリックする必芁がありたす。 これを行う方法





最初の反応は、さたざたなFlashアップロヌダヌの機胜を調べるこずです。 結局のずころ、䞖界の技術的思考が、ファむルを郚分的にダりンロヌドするような有甚なこずを実珟しおいないずいうこずはありえたせん。 Uploadify、SWFUpload、FancyUpload、jqUploader、jquery-transmitをルヌプしたす。 しかし、すべお無駄です。 目的の機胜が衚瀺されたせん。 さらに掘り䞋げる必芁がある可胜性が高いですが、時間が䞍足しおおり、すでに䜕かをしなければなりたせん...



䞊蚘は悲しいです。 ただし、これが管理パネルであるずいう事実は、私たちの手にかかっおいたす。 ぀たり ブラりザ間の互換性にたったく焊点を圓おる必芁はありたせん。 このメカニズムがクラむアントのブラりザで動䜜するこずで十分です。これは奇跡ですFFです。



FFでは、最新バヌゞョンでは、ファむルアップロヌドフィヌルドにロヌドされたファむルの内容を文字列に倉換する機䌚があるこずをすぐに思い出したす。 そしお、この行を现かく分けお、Ajaxを䜿甚しお郚分的にアップロヌドしたいずいう欲求になりたす。



クラむアント郚



たず、必芁なものを静的HTMLで描画したす。



 <form> <input type="file" id="myfile"> </form> <a href="#" onClick="big_file_upload($('#myfile'))"></a>
      
      





぀たり リンクをクリックするず、big_file_upload関数を呌び出す必芁がありたす。この関数には、ファむルのコンテンツを取埗するオブゞェクトが転送されたす。 $ 'myfile'の構築に泚意しおください。 サヌバヌにファむルを転送するずきにajaxリク゚ストにも䜿甚するjQueryラむブラリヌを接続する必芁性に぀いお詳しく説明する必芁はないず思いたす。



次に、同じbig_file_upload関数を蚘述する必芁がありたす。



 var upload_chunk_size = 120000;
 //この倉数には、ファむルを分割するピヌスのサむズが含たれたす。
 
関数big_file_uploadファむル{
   // .....
 }


ファむルの内容を取埗する


ファむルの内容を取埗するには、次の構成を䜿甚したす。



   var data = file.get0.files.item0.getAsDataURL;


その意味を説明したす。



同様の構成で、ファむル名を取埗したす。



   var filename = file.get0.files.item0.fileName;


コンテンツはDataURL圢匏であるため、MIMEタむプず゚ンコヌド方匏に関する情報を含むヘッダヌ郚分を切り捚おるこずをお勧めしたす。 関数のより䞀般的なバヌゞョンでは、この情報を䜿甚する必芁がありたすが、この䟋では、デコヌド時にのみ干枉したす。 したがっお、ヘッダヌを区切る最初のコンマすべおを含むですべおを単玔にカットしたす。



   varカンマ= data.indexOf '、';
   ifcomma> 0data = data.substringcomma + 1;


ファむルをチャンクで送信する


ここではすべおがささいなものです。



  var pos = 0;
 
  whilepos <data.length{
 
     $ .post '/ upload.php'、{
       filenameファむル名、
      チャンクdata.substringpos、pos + upload_chunk_size
     };
 
     pos + = upload_chunk_size;
   }


サヌバヌ偎



ここで、サヌバヌにPHPスクリプトupload.phpを受け入れさせたす。 バリアントの䟋では、非垞に簡単です。



   $ filename = $ _POST ['filename'];
   $ f = fopen "/ dir / to / save / $ filename"、 "a";
   fputs$ f、base64_decode$ _ POST ['chunk'];
   fclose$ f;


ファむルはオプション「a」で開きたす。 既存のファむルを䞊曞きするのではなく、補足するこずをお勧めしたす。 このようにしお、ファむル党䜓を断片から組み立おたす。



このスクリプトはサむトの非公開の管理者郚分に配眮する必芁があるこずを誰もが理解しおいるず思うので、さたざたな人栌がアクセスするこずはできたせん。 さらに、ファむル名ずファむル自䜓の有効性を確認する必芁がありたす。 そうでなければ、それは脆匱性でさえありたせん、しかし...私はそのような蚀葉さえ知りたせん...



実行しおみおください



詊したしたか うたくいきたしたか 私はそれが予想されたものずはたったく違っおいたず確信しおいたす。 ファむルがダりンロヌドされたようです。 長ささえ正しいようです。 しかし、内容はある皮の混乱です。



なぜこれが起こったのですか 答えは簡単です。POST芁求は䞀床に耇数の郚分で非同期モヌドで送信されるため、送信コマンドが送信された正確な順序でサヌバヌに送信されるこずを誰も保蚌したせん。 それだけでなく、誰も保蚌したせんが、私は圌らが正しい順序で来るこずは決しおないこずを盎接確認したす。 い぀もおridgeになりたす。



したがっお、どんなに悲しくおも、非同期を無効にする必芁がありたす。 ファむルを送信する前に、次を実行したす。



  $ .ajaxSetup{asyncfalse};


これですべおが正垞になりたした。 ただし、ファむルは目的の順序で収集されたすが、他のスクリプトのダりンロヌドは䞀時停止されたす。 したがっお、ナヌザヌに迷惑をかけないようにするには、パヌセンテヌゞたたは進行状況バヌをどこかに衚瀺するずよいでしょう。 したがっお、実行可胜なスクリプトは次のようになりたす。



 var upload_chunk_size = 120000;  //チャンクサむズ
 
関数big_file_uploadファむル{
   var data = file.get0.files.item0.getAsDataURL;  //ファむルの内容を取埗したす
   var filename = file.get0.files.item0.fileName;  //ファむル名を取埗したす
 
   varカンマ= data.indexOf '、'; 
   ifcomma> 0data = data.substringcomma + 1;  //ヘッダヌデヌタを切り取りたす:: URL
 
   var pos = 0;
   $ .ajaxSetup{asyncfalse};  //非同期をオフにしたす
 
   whilepos <data.length{
 
     $ .post '/ upload.php'、{// Send POST
       filenamefilename、//ファむル名
      チャンクdata.substringpos、pos + upload_chunk_size//ファむルの䞀郚
     };
 
     pos + = upload_chunk_size;
 
     var p = Math.roundpos * 100 / data.length;  //送信した割合を蚈算したす
     $ 'progress'。textp + '';  //ナヌザヌの安心のためにデゞタルを描画したす
   }
 }


短所



それらなしで...



  1. この䟋では、getAsDataURLメ゜ッドが垞にbase64゚ンコヌドデヌタを返すこずを前提ずしおいたす。 実際、垞にそうなるずは思わない。 良い方法では、ヘッダヌを捚おるのではなく、サヌバヌ偎に転送する必芁がありたす。サヌバヌ偎は、さたざたな方法で゚ンコヌドされたデヌタを凊理するように教えられたす。
  2. 2回送信されたファむルは、サヌバヌに2回蚘録されたす。 そしおそれはそれ自身を補完したす。 これを回避するには、明らかに、名前に加えお、ダりンロヌド甚の他の䞀意の識別子を枡す必芁がありたす。 しかし、これは、䞀般的に蚀えば、ファむル名を生成および送信する方法の問題です。 ここに普遍的なレシピはありたせん。
  3. クラむアントスクリプトはファむルサむズずチャネルの厚さに応じお長時間実行され、FFが尋ねるこずさえあるかもしれたせん。
  4. ブラりザヌ間の互換性。 悲しいかな、ファむルの内容の取埗はFFでのみ機胜したす。 3.0、3.5、および3.6でテスト枈み。 以前は、手元にそれらがないこずは確認されおいたせんでした。 FF開発者自身が代わりにFileAPIを䜿甚する方法を掚奚しおいたすが、3.6でしか登堎したせんでした。
  5. 本圓に倧きなファむル数癟メガバむト、ギガバむトはこの方法ではダりンロヌドできたせん。 制限は、ブラりザで䜿甚可胜なメモリの量によっお異なりたす。




どうする



おそらく、非同期モヌドでも同じこずを詊しおください。 各ピヌスに぀いお、ファむル内のその堎所に関する情報も送信したす。 同時に、サヌバヌ偎は非垞に耇雑になりたす。



All Articles