웹 프론트엔드 JS 튜토리얼 iframe, FormData 및 FileReader_javascript 기술을 기반으로 새로 고치지 않고 파일을 업로드하는 세 가지 방법에 대해 이야기해 보세요.

iframe, FormData 및 FileReader_javascript 기술을 기반으로 새로 고치지 않고 파일을 업로드하는 세 가지 방법에 대해 이야기해 보세요.

May 16, 2016 pm 03:27 PM
formdata iframe

요청을 보내는 방법에는 두 가지가 있습니다. 하나는 ajax를 사용하는 것이고, 다른 하나는 양식 제출을 사용하는 것입니다. 기본 양식 제출이 처리되지 않으면 페이지가 리디렉션됩니다. 간단한 데모를 통해 설명하겠습니다.


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의 데이터 매개변수로 formData를 사용하고, contentType: false와 processData: false를 동시에 설정하여 jQuery에 요청 헤더와 전송된 데이터를 처리하지 않도록 지시할 수 있습니다.

이 제출 방법은 ajax와 동일한 것 같지만 완전히 동일하지는 않습니다. 양식 제출에는 세 가지 데이터 형식이 있으므로 파일을 업로드하려면 multipart/form-data여야 합니다. 위의 양식 제출 요청에서 http 헤더 정보의 Content-Type은 multipart/form-data인 반면 일반 Ajax 제출은 application/json입니다. 양식으로 제출된 전체 콘텐츠 유형은 다음과 같습니다.

"콘텐츠 유형":"다중 부분/양식 데이터; 경계=------WebKitFormBoundaryYOE7pWLqdFYSeBFj"

multipart/form-data 외에도 경계도 지정됩니다. 이 경계의 목적은 다양한 필드를 구별하는 것입니다. FormData 객체는 불투명하므로 JSON.stringify를 호출하면 빈 객체 {}가 반환됩니다. 동시에 FormData는 추가 메서드만 제공하므로 실제로 업로드된 FormData의 콘텐츠를 가져올 수는 없지만 데이터를 통해 볼 수는 있습니다. 분석 도구 또는 서비스를 통해 수신됩니다. 위의 텍스트 파일을 업로드할 경우 서비스가 수신하는 POST 데이터의 원래 형식은 다음과 같습니다.

------WebKitFormBoundaryYOE7pWLqdFYSeBFj

콘텐츠 처리: 양식-데이터 이름="사용자"

abc

------WebKitFormBoundaryYOE7pWLqdFYSeBFj

콘텐츠 처리: form-data; name="file"; 콘텐츠 유형: 텍스트/일반

텍스트 파일의 내용입니다.

------WebKitFormBoundaryYOE7pWLqdFYSeBFj--

위 서비스에서 수신한 데이터에서 FormData가 제출한 형식을 확인할 수 있습니다. 각 필드는 경계로 구분되고 --로 끝납니다. Ajax 요청의 경우 전송된 데이터 형식은 일반적으로 키=값과 중간에 &를 사용하여 사용자 정의됩니다.


 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 Hentai를 무료로 생성하십시오.

뜨거운 도구

메모장++7.3.1

메모장++7.3.1

사용하기 쉬운 무료 코드 편집기

SublimeText3 중국어 버전

SublimeText3 중국어 버전

중국어 버전, 사용하기 매우 쉽습니다.

스튜디오 13.0.1 보내기

스튜디오 13.0.1 보내기

강력한 PHP 통합 개발 환경

드림위버 CS6

드림위버 CS6

시각적 웹 개발 도구

SublimeText3 Mac 버전

SublimeText3 Mac 버전

신 수준의 코드 편집 소프트웨어(SublimeText3)

HTML에서 IFrame을 어떻게 자르나요? HTML에서 IFrame을 어떻게 자르나요? Aug 29, 2023 pm 04:33 PM

인라인 프레임은 HTML에서 iframe이라고 합니다. 레이블은 브라우저가 스크롤 막대와 테두리를 사용하여 다양한 문서를 표시할 수 있는 콘텐츠 내 직사각형 영역을 지정합니다. 현재 HTML 문서 내에 다른 문서를 포함하려면 인라인 프레임을 사용하십시오. 요소에 대한 참조는 HTMLiframe 이름 속성을 사용하여 지정할 수 있습니다. JavaScript에서는 name 속성을 사용하여 요소에 대한 참조도 이루어집니다. iframe은 기본적으로 현재 표시된 웹페이지 내에 웹페이지를 표시하는 데 사용됩니다. iframe을 포함하는 문서의 URL은 "src" 속성을 사용하여 지정됩니다. 구문 다음은 HTML <iframesrc="URL"title="d의 구문입니다.

iframe의 데이터 ID는 무엇을 의미합니까? iframe의 데이터 ID는 무엇을 의미합니까? Aug 28, 2023 pm 02:25 PM

iframe의 data-id는 특정 요소의 식별자를 저장하기 위해 HTML 태그에 사용되는 맞춤 속성을 나타냅니다. data-id 속성을 사용하면 iframe 요소에 고유 식별자를 추가하여 JavaScript에서 조작하고 액세스할 수 있습니다. data-id 속성의 이름 지정은 특정 요구 사항에 따라 사용자 정의할 수 있지만 일반적으로 고유성과 가독성을 보장하기 위해 일부 명명 규칙을 따릅니다. data-id 속성은 특정 iframe을 식별하고 조작하는 데에도 사용할 수 있습니다.

iframe이 느리게 로드되는 이유는 무엇입니까? iframe이 느리게 로드되는 이유는 무엇입니까? Aug 24, 2023 pm 05:51 PM

iframe 로딩이 느린 이유에는 주로 네트워크 지연, 긴 리소스 로딩 시간, 로딩 순서, 캐싱 메커니즘 및 보안 정책이 포함됩니다. 자세한 소개: 1. 네트워크 지연. 브라우저가 iframe이 포함된 웹 페이지를 로드할 때 iframe의 콘텐츠를 얻기 위해 서버에 요청을 보내야 합니다. 네트워크 지연이 길면 콘텐츠를 얻는 데 시간이 걸립니다. 2. 리소스 로딩 시간이 길거나, 리소스 크기가 크거나, 서버 응답 시간이 길면 로딩 속도가 더욱 느려집니다. 등.

iframe을 대체할 수 있는 기술 iframe을 대체할 수 있는 기술 Aug 24, 2023 pm 01:53 PM

iframe을 대체할 수 있는 기술에는 Ajax, JavaScript 라이브러리 또는 프레임워크, 웹 구성 요소 기술, 프런트 엔드 라우팅 및 서버 측 렌더링이 포함됩니다. 자세한 소개: 1. Ajax는 동적 웹 페이지를 만드는 데 사용되는 기술입니다. 전체 페이지를 새로 고치지 않고도 백그라운드에서 서버와 데이터를 교환하여 페이지의 비동기 업데이트를 달성할 수 있습니다. Ajax를 사용하면 콘텐츠를 보다 유연하게 로드하고 표시할 수 있으며, 다른 페이지를 삽입하기 위해 iframe을 사용할 필요가 없습니다. 또는 React 등과 같은 프레임워크.

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와는 관련이 없습니다. 마이크로소프트의 사본

iframe의 로딩 이벤트는 무엇입니까? iframe의 로딩 이벤트는 무엇입니까? Aug 28, 2023 pm 01:55 PM

iframe의 로딩 이벤트에는 onload 이벤트, onreadystatechange 이벤트, onbeforeunload 이벤트, onerror 이벤트, onabort 이벤트 등이 포함됩니다. 자세한 설명: 1. onload 이벤트는 iframe을 로드한 후 실행될 JavaScript 코드를 지정합니다. 2. onreadystatechange 이벤트는 iframe 상태가 변경될 때 실행될 JavaScript 코드를 지정합니다.

iframe의 위험은 무엇입니까? iframe의 위험은 무엇입니까? Sep 08, 2023 pm 03:14 PM

iframe의 위험은 주로 다음과 같습니다. 1. 악성 웹 페이지는 iframe을 통해 다른 웹 페이지를 로드하고 일부 공격을 수행할 수 있습니다. 2. 동일 출처 정책의 돌파구인 iframe에서 웹 페이지를 로드합니다. 악의적인 공격을 받을 수 있는 도메인 간 통신 전략이 위반될 수 있습니다. 3. 코드 실행 문제, iframe에 로드된 웹 페이지가 JS 코드를 실행할 수 있어 일부 보안 문제가 발생할 수 있습니다. iframe 등을 통해 로드된 콘텐츠를 올바르게 구문 분석하고 색인을 생성할 수 없습니다.

Python에서 iframe은 무엇을 의미합니까? Python에서 iframe은 무엇을 의미합니까? Aug 25, 2023 pm 03:24 PM

Python의 iframe은 웹 페이지에 다른 웹 페이지나 문서를 삽입하는 데 사용되는 HTML 태그입니다. Python에서는 다양한 라이브러리와 프레임워크를 사용하여 iframe을 처리하고 조작할 수 있으며, 그 중 가장 일반적으로 사용되는 것은 웹 페이지에서 iframe의 콘텐츠를 쉽게 추출하고 조작하고 처리할 수 있는 BeautifulSoup 라이브러리입니다. iframe을 처리하고 조작하는 방법을 아는 것은 웹 개발과 데이터 스크래핑 모두에 매우 유용합니다.

See all articles