ホームページ ウェブフロントエンド jsチュートリアル iframe、FormData、FileReader_javascript のスキルに基づいて、更新せずにファイルをアップロードする 3 つの方法について説明します。

iframe、FormData、FileReader_javascript のスキルに基づいて、更新せずにファイルをアップロードする 3 つの方法について説明します。

May 16, 2016 pm 03:27 PM
formdata iframe

リクエストを送信するには 2 つの方法があります。1 つは ajax を使用する方法、もう 1 つはフォーム送信を使用する方法です。デフォルトのフォーム送信が処理されない場合、ページはリダイレクトされます。簡単なデモを使って説明してみましょう:


html は次のとおりです。要求されたパス アクションは「アップロード」であり、他の処理は行われません。

 <form method="POST" action="upload" enctype="multipart/form-data">
  名字 <input type="text" name="user"></input>
  头像 <input type="file" name="file"></input>
  <input type="submit" id="_submit" value="提交"></input>
 </form> 
ログイン後にコピー

サーバー (ノード) の応答は、「受信したフォーム データ」を直接返します。デモは次のとおりです。

デフォルトでは、フォームがアップロードを要求し、同時にアップロードにリダイレクトしていることがわかります。ただし、多くの場合、フォーム リクエストが ajax のようになり、ページのリダイレクトや更新が行われないことが望まれます。上記のシナリオと同様に、アップロードが完了すると、ユーザーが選択したアバターが現在のページに表示されます。

最初の解決策は、html5 の FormData を使用し、フォーム内のデータを FormData オブジェクトにカプセル化し、それを POST で送信することです。次のコードに示すように、コードの 6 行目でフォームの DOM オブジェクトを取得し、8 行目で FormData のインスタンスを構築し、18 行目でフォーム データを送信します。

document.getElementById("_submit").onclick = function(event){
   //取消掉默认的form提交方式
   if(event.preventDefault) event.preventDefault();
   else event.returnValue = false;       //对于IE的取消方式
   var formDOM = document.getElementsByTagName("form")[];
   //将form的DOM对象当作FormData的构造函数
   var formData = new FormData(formDOM);
   var req = new XMLHttpRequest();
   req.open("POST", "upload");
   //请求完成
   req.onload = function(){
    if(this.status === ){
      //对请求成功的处理
    }
   }
   //将form数据发送出去
   req.send(formData);
       //避免内存泄漏
       req = null;
 } 
ログイン後にコピー

アップロードが成功すると、サービスは画像のアクセス アドレスを返し、成功したリクエストを処理するために 14 行を追加します。アップロードされた画像を送信ボタンの上に表示します。

var img = document.createElement("img");
     img.src = JSON.parse(this.responseText).path;
     formDOM.insertBefore(img, document.getElementById("_submit")); 
ログイン後にコピー

例:


jQuery を使用する場合は、ajax の data パラメーターとして formData を使用し、contentType: false と processData: false を同時に設定して、jQuery にリクエスト ヘッダーと送信されたデータを処理しないように指示できます。

この送信方法は ajax と同じように見えますが、まったく同じではありません。フォーム送信には 3 つのデータ形式があるため、ファイルをアップロードする場合は multipart/form-data でなければなりません。上記のフォーム送信リクエストの http ヘッダー情報の Content-Type は multipart/form-data ですが、通常の ajax 送信は application/json です。フォームによって送信された完全な Content-Type は次のとおりです:

"コンテンツタイプ":"マルチパート/フォームデータ; 境界=-----WebKitFormBoundaryYOE7pWLqdFYSeBFj"

multipart/form-data に加えて、境界も指定されます。この境界の目的は、さまざまなフィールドを区別することです。 FormData オブジェクトは不透明であるため、JSON.stringify を呼び出すと空のオブジェクト {} が返されます。同時に、FormData は append メソッドのみを提供するため、実際にアップロードされた FormData のコンテンツは取得できませんが、データを通じて表示できます。分析ツールまたはサービスによって受信されます。上記のテキスト ファイルをアップロードした場合、サービスが受信する POST データの元の形式は次のとおりです:

------WebKitFormBoundaryYOE7pWLqdFYSeBFj

コンテンツの配置: フォームデータ名 = "ユーザー"

ABC

------WebKitFormBoundaryYOE7pWLqdFYSeBFj

コンテンツの配置: フォームデータ; ファイル名 = "test.txt"; コンテンツタイプ: text/plain

これはテキスト ファイルの内容です。

------WebKitFormBoundaryYOE7pWLqdFYSeBFj--

上記のサービスで受信したデータから、FormData によって送信された各フィールドが境界で区切られ、- で終わっていることがわかります。 Ajax リクエストの場合、送信されるデータ形式はカスタマイズされており、通常は key=value と中間の & が使用されます:


 var req = new XMLHttpRequest();
  var sendData = "user=abc&file=这是一个文本文件的内内容";
  req.open("POST", "upload");
  //发送的数据需要转义,见上面提到的三种格式
  req.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
  req.send(sendData); 
ログイン後にコピー

服务就会收到和send发出去的字符串一模一样的内容,然后再作参数解析,所以就得统一参数的格式:

user=abc&file=这是一个文本文件的内容

从这里可以看出POST本质上并不比GET安全,POST只是没有将数据放在网址传送而已。

考虑到FormData到了IE10才支持,如果要支持较低版本的IE,那么可以借助iframe。

文中一开始就说,默认的form提交会使页面重定向,而重定向的规则在target中指定,可以和a标签一样指定为"_blank",在新窗口中打开;还可以指定为一个iframe,在该iframe中打开。所以可以弄一个隐藏的iframe,将form的target指向这个iframe,当form请求完成时,返回的数据就会由这个iframe显示,正如上面在新页面显示的:"Recieved form data"。请求完成后,iframe加载完成,触发load事件,在load事件的处理函数里,获取该iframe的内容,从而拿到服务返回的数据了!拿到后再把iframe删掉。

在提交按钮的响应函数里,首先创建一个iframe,设置iframe为不可见,然后再添加到文档里:

var iframe = document.createElement("iframe");
  iframe.width = 0;
  iframe.height = 0;
  iframe.border = 0;
  iframe.name = "form-iframe";
  iframe.id = "form-iframe";
  iframe.setAttribute("style", "width:0;height:0;border:none");
  //放到document
  this.form.appendChild(iframe); 
ログイン後にコピー

改变form的target为iframe的name值:

 this.form.target = "form-iframe"; 
ログイン後にコピー

然后再响应iframe的load事件:

 iframe.onload = function(){
   var img = document.createElement("img");
   //获取iframe的内容,即服务返回的数据
   var responseData = this.contentDocument.body.textContent || this.contentWindow.document.body.textContent;
   img.src = JSON.parse(responseData).path;
   f.insertBefore(img, document.getElementById("_submit"));
   //删掉iframe
   setTimeout(function(){
    var _frame = document.getElementById("form-iframe");
    _frame.parentNode.removeChild(_frame);
   }, 100);
   //如果提示submit函数不存在,请注意form里面是否有id/value为submit的控件
   this.form.submit();
  } 
ログイン後にコピー

第二种办法到这里就基本可以了,但是如果看163邮箱或者QQ邮箱上传文件的方式,会发现和上面的两种方法都不太一样。用httpfox抓取请求的数据,会发现上传的内容的格式并不是上面说的用boundary隔开,而是直接把文件的内容POST出去了,而文件名、文件大小等相关信息放在了文件的头部。如163邮箱:

POST Data:

this is a text

Headers:

Mail-Upload-name: content.txt
Mail-Upload-size: 15

可以推测它们应该是直接读取了input文件的内容,然后直接POST出去了。要实现这样的功能,可以借助FileReader,读取input文件的内容,再保留二进制的格式发送出去:

 var req = new XMLHttpRequest();
   req.open("POST", "upload");
   //设置和邮箱一样的Content-Type
   req.setRequestHeader("Content-Type", "application/octet-stream");
   var fr = new FileReader();
   fr.onload = function(){
    req.sendAsBinary(this.result);
   }
   req.onload = function(){
     //一样,省略
   }
    //读取input文件内容,放到fileReader的result字段里
   fr.readAsBinaryString(this.form["file"].files[0]); 
ログイン後にコピー

代码第13行执行读文件,读取完毕后触发第6行的load响应函数,第7行以二进制文本形式发送出去。由于sendAsBinary的支持性不是很好,可以自行实现一个:

 if(typeof XMLHttpRequest.prototype.sendAsBinary === 'undefined'){
  XMLHttpRequest.prototype.sendAsBinary = function(text){
  var data = new ArrayBuffer(text.length);
  var uia = new UintArray(data, );
  for (var i = ; i < text.length; i++){ 
   uia[i] = (text.charCodeAt(i) & xff);
  }
  this.send(uia);
  }
 } 
ログイン後にコピー

代码的关键在于第6行,将字符串转成8位无符号整型,还原二进制文件的内容。在执行了fr.readAsBinaryString之后,二进制文件的内容将会以utf-8的编码以字符串形式存放到result,上面的第6行代码将每个unicode编码转成整型(&0xff或者parseInt),存放到一个8位无符号整型数组里面,第8行把这个数组发送出去。如果直接send,而不是sendAsBinary,服务收到的数据将无法正常还原成原本的文件。

上面的实现需要考虑文件太大,需分段上传的问题。

关于FileReader的支持性,IE10以上支持,IE9有另外一套File API。

文章讨论了3种办法实现无刷新上传文件,分别是使用iframe、FormData和FileReader,支持性最好是的iframe,但是从体验的效果来看FormData和FileReader更好,因为这两者不用生成一个无用的DOM再删除,其中FormData最简单,而FileReader更加灵活。

面给大家介绍iframe无刷新上传文件

form.html
<form enctype="multipart/form-data" method="post" target="upload" action="upload.php" > 
<input type="file" name="uploadfile" />
<input type="submit" /> 
</form> 
<iframe name="upload" style="display:none"></iframe> 
ログイン後にコピー

ホットAIツール

Undresser.AI Undress

Undresser.AI Undress

リアルなヌード写真を作成する AI 搭載アプリ

AI Clothes Remover

AI Clothes Remover

写真から衣服を削除するオンライン AI ツール。

Undress AI Tool

Undress AI Tool

脱衣画像を無料で

Clothoff.io

Clothoff.io

AI衣類リムーバー

AI Hentai Generator

AI Hentai Generator

AIヘンタイを無料で生成します。

ホットツール

メモ帳++7.3.1

メモ帳++7.3.1

使いやすく無料のコードエディター

SublimeText3 中国語版

SublimeText3 中国語版

中国語版、とても使いやすい

ゼンドスタジオ 13.0.1

ゼンドスタジオ 13.0.1

強力な PHP 統合開発環境

ドリームウィーバー CS6

ドリームウィーバー CS6

ビジュアル Web 開発ツール

SublimeText3 Mac版

SublimeText3 Mac版

神レベルのコード編集ソフト(SublimeText3)

HTML で IFrame をトリミングするにはどうすればよいですか? HTML で IFrame をトリミングするにはどうすればよいですか? Aug 29, 2023 pm 04:33 PM

インラインフレームはHTMLではiframeと呼ばれます。ラベルは、ブラウザがスクロール バーや枠線を使用してさまざまなドキュメントを表示できる、コンテンツ内の長方形の領域を指定します。現在の HTML ドキュメント内に別のドキュメントを埋め込むには、インライン フレームを使用します。要素への参照は、HTMLiframe name 属性を使用して指定できます。 JavaScript では、要素への参照も name 属性を使用して行われます。 iframe は基本的に、現在表示されている Web ページ内に Web ページを表示するために使用されます。 iframe を含むドキュメントの URL は、「src」属性を使用して指定されます。構文 以下は HTML <iframesrc="URL"title="d の構文です。

iframe の読み込みが遅いのはなぜですか? iframe の読み込みが遅いのはなぜですか? Aug 24, 2023 pm 05:51 PM

iframe の読み込みが遅い原因には、主にネットワーク遅延、リソース読み込み時間の長さ、読み込み順序、キャッシュ メカニズム、セキュリティ ポリシーが含まれます。詳細な紹介: 1. ネットワーク遅延: ブラウザーが iframe を含む Web ページを読み込むとき、iframe 内のコンテンツを取得するためにサーバーにリクエストを送信する必要があります。ネットワーク遅延が大きい場合、コンテンツの取得に時間がかかります。 ; 2. リソースの読み込み時間が長い場合、リソースのサイズが大きい場合、またはサーバーの応答時間が長い場合、読み込み速度はより明らかに遅くなります; 3. 読み込みシーケンス、等

iframe の data-id は何を意味しますか? iframe の data-id は何を意味しますか? Aug 28, 2023 pm 02:25 PM

iframe の data-id は、特定の要素の識別子を格納するために HTML タグで使用されるカスタム属性を指します。 data-id 属性を使用すると、iframe 要素に一意の識別子を追加して、JavaScript で操作およびアクセスできるようにすることができます。 data-id 属性の命名は、特定のニーズに応じてカスタマイズできますが、一意性と読みやすさを確保するために、通常はいくつかの命名規則に従います。 data-id 属性を使用して、特定の iframe を識別および操作することもできます。

Microsoft: Outlook エラーにより、アクセスするたびに「TokenFactoryIframe」ファイルがダウンロードされる Microsoft: Outlook エラーにより、アクセスするたびに「TokenFactoryIframe」ファイルがダウンロードされる Apr 19, 2023 am 08:25 AM

ユーザーが Safari ブラウザを通じて電子メール サービスにアクセスすると、Microsoft Outlook は macOS 上に「TokenFactoryIframe」と呼ばれる謎のファイルをダウンロードします。この問題は現在、Outlook がアクセスするたびにダウンロードする「TokenFactoryIframe」ファイルを発見したユーザーによって広く報告されています。 Outlook は、数秒ごと、または少なくとも Apple プラットフォーム上の Outlook にアクセスするたびに、この謎のファイルをダウンロードします。私たちの調査結果によると、これは Outlook に投稿されたサーバー側の誤った更新によって引き起こされる問題のようであり、Safari や macOS とは関係がありません。 Microsoft のコピー

iframe に代わるテクノロジーは何ですか iframe に代わるテクノロジーは何ですか Aug 24, 2023 pm 01:53 PM

iframe を置き換えることができるテクノロジには、Ajax、JavaScript ライブラリまたはフレームワーク、Web コンポーネント テクノロジ、フロントエンド ルーティング、サーバー側レンダリングなどがあります。詳細な紹介: 1. Ajax は、動的な Web ページを作成するために使用されるテクノロジです。ページ全体を更新することなく、バックグラウンドでサーバーとデータをやり取りすることでページの非同期更新を実現 Ajaxを使用することでより柔軟にコンテンツを読み込んで表示できるほか、他のページを埋め込むためにiframeを使用する必要もありません 2. JavaScriptライブラリまたは React などのフレームワーク。

iframeの読み込みイベントとは何ですか? iframeの読み込みイベントとは何ですか? Aug 28, 2023 pm 01:55 PM

iframe の読み込みイベントには、onload イベント、onreadystatechange イベント、onbeforeunload イベント、onerror イベント、onabort イベントなどが含まれます。詳細説明: 1. onload イベント、iframe のロード後に実行される JavaScript コードを指定、2. onreadystatechange イベント、iframe の状態が変化したときに実行される JavaScript コードを指定、など。

Python での iframe とは何ですか? Python での iframe とは何ですか? Aug 25, 2023 pm 03:24 PM

Python の iframe は、Web ページに別の Web ページまたはドキュメントを埋め込むために使用される HTML タグです。 Python では、さまざまなライブラリとフレームワークを使用して iframe を処理および操作できます。その中で最も一般的に使用されるのは BeautifulSoup ライブラリで、Web ページから iframe のコンテンツを簡単に抽出して操作および処理できます。 iframe の処理方法を知ることは、Web 開発とデータ スクレイピングの両方に非常に役立ちます。

iframe の危険性とは iframe の危険性とは Sep 08, 2023 pm 03:14 PM

iframe の危険性は主に次のとおりです: 1. セキュリティの脆弱性: 悪意のある Web ページが iframe 経由で他の Web ページをロードし、攻撃を実行する可能性がある; 2. 同一オリジン ポリシーの突破: iframe で他のドメイン名で Web ページをロードすることにより、同じ -オリジンポリシーが侵害される可能性があるクロスドメイン通信を実現するための戦略(悪意のある攻撃を受ける可能性がある)、3. コード実行の問題、iframe にロードされた Web ページで JS コードが実行される可能性があり、セキュリティ上の問題が発生する可能性がある、4. SEO の問題、検索エンジンiframe などを介して読み込まれたコンテンツを正しく解析してインデックスを作成できない場合があります。

See all articles