IE8에서 양식 데이터를 비동기 적으로 전송하여 json 응답을 받습니다.

form 가 가지는 데이터를 JavaScript 로부터 취득하기 위한 API 로서 FormData 라는 클래스가 존재한다.
이것을 이용하면, Ajax 로 파일을 업로드할 수 있게 된다.

그런데 이 FormData 는 IE8, 9 에서는 이용할 수 없다 (IE10 이상이라면 이용할 수 있다).

IE8에서도 비동기적으로 form의 데이터를 송신하고 싶은 경우는 <iframe> 태그를 이용한 (약간 까다로운) 방법이 존재한다.

환경



웹 브라우저



IE11 (개발자 모드에서 IE8을 에뮬레이트하여 확인)

AP 서버



Payara 4.1.154

자바



JDK 1.8.0_60

구조적인




  • <form> 태그에 target 속성을 설정한다.
  • target 에는 같은 <html> 에 존재하는 <iframe>name 를 지정한다.
  • <iframe> 태그는, display: none; 등을 사용해 보이지 않게 해 둔다.
  • <form>를 제출하면 요청 결과는 target에 지정된 <iframe>로 출력됩니다.
  • 이 때문에, 화면 천이는 일어나지 않고 Ajax 로 비동기 통신한 것 같은 동작이 된다.

  • 구현적인



    클라이언트



    index.html
    <!DOCTYPE html>
    <html>
      <head>
        <meta charset="UTF-8" />
        <title>sample</title>
        <style>
          .invisible {
            display: none;
          }
        </style>
      </head>
      <body>
        <form id="form" action="sample-servlet" method="POST" target="_frame">
          <input type="text" name="text" />
          <input type="submit" value="Submit" />
    
          <iframe id="frame" name="_frame" class="invisible"></iframe>
        </form>
    
        <script src="https://code.jquery.com/jquery-1.11.3.min.js"></script>
        <script src="script.js"></script>
      </body>
    </html>
    

    script.js
    $(function() {
        $('#frame').on('load', function() {
            var json = $(this).contents().text();
            var response = $.parseJSON(json);
            alert('foo=' + response.foo + ', bar=' + response.bar);
        });
    });
    

    서버



    SampleServlet.java
    package jta_sample;
    
    import java.io.BufferedReader;
    import java.io.IOException;
    import java.io.PrintWriter;
    
    import javax.servlet.ServletException;
    import javax.servlet.annotation.WebServlet;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    
    @WebServlet("/sample-servlet")
    public class SampleServlet extends HttpServlet {
    
        @Override
        protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            try (BufferedReader br = req.getReader();) {
                br.lines().forEach(System.out::println);
            }
    
            // ★ Content-Type に text/plain を指定
            resp.setHeader("Content-Type", "text/plain");
    
            try (PrintWriter pw = resp.getWriter();) {
                pw.println("{\"foo\": \"xxx\", \"bar\": true}");
            }
        }
    }
    

    동작 확인





    개발자 모드에서 IE8 로 실행.

    ↓ 제출



    서버측 출력
    2015-11-08T23:18:16.533+0900|情報: text=abcdefg
    

    설명



    응답을 받으려면



    script.js
        $('#frame').on('load', function() {
            var json = $(this).contents().text();
            var response = $.parseJSON(json);
            alert('foo=' + response.foo + ', bar=' + response.bar);
        });
    
  • <iframe> load 이벤트를 모니터링하여 서버로부터 응답을 받을 수 있습니다.
  • 스테이터스 코드등은 참조할 수 없기 때문에 , 응답에 성공인가 에러인지 알 수 있는 식별자를 건네줄 필요가 있을 것 같다.

  • 콘텐츠 형식에 text/plain 지정



    SampleServlet.java
        resp.setHeader("Content-Type", "text/plain");
    

    json을 반환하기 때문에 application/json로 만들고 싶지만 IE는 파일 다운로드를 시작합니다.

    Content-Type을 application/json으로 설정한 경우



    기분 나쁘지만, text/plain 로 해 줄 필요가 있는 것 같다.
    (JAX-RS 를 사용하고 있으면, JSON 변환을 위한 MessageBodyWriter 와 제휴하기 위해서 메소드를 @Produces(MediaType.APPLICATION_JSON) 로 어노테이트하고 싶어지지만, 그러면 파일 다운로드가 되어 버리므로 치아가 유이)

    참고


  • ajax-fileupload enable ie8+10 by iframe chokuryu/main.js|
  • Ajax로 이미지와 같은 파일을 업로드하는 방법 :: Hub Rogu
  • 좋은 웹페이지 즐겨찾기