Request Character Encoding Problem

สมชัย หลิมศิโรรัตน์

1 กุมภาพันธ์ 2549

ปัญหา

ข้อมูลที่ส่งมายัง Server (Tomcat) จากการกด submit แบบฟอร์มนั้น หากข้อมูลเข้ารหัสเป็นภาษาไทย หรือภาษาอื่นๆที่ไม่ใช่รหัสแบบ ISO 8859-1 (Latin-1) จะถูกถอดรหัสผิดพลาด กลายเป็นเครื่องหมาย ?

สาเหตุ

เนื่องจากตามมาตรฐานแล้ว เมื่อ Browser ส่ง Request มายัง Server จะต้องส่งข้อมูลเกี่ยวกับการเข้ารหัสตัวอักษรมาด้วย ซึ่งจะทำให้ Server รู้ว่าข้อมูลที่ส่งมานั้นจะถอดรหัสออกมาได้อย่างไร

แต่ Browser ในปัจจุบัน เช่น IE ไม่ได้ทำตามมาตรฐานทั้งหมด ซึ่ง Browser บางตัวไม่ได้ส่งข้อมูลเกี่ยวกับการเข้ารหัสมาให้ Server ดังนั้น Server จึงไม่รู้ว่าจะถอดรหัสออกมาได้อย่างไร ซึ่งโดยปกติแล้ว Server ก็จะเลือกรหัสใดรหัสหนึ่งเป็นค่า default

สำหรับ Tomcat จะเลือกใช้รหัสแบบ ISO 8859-1 ซึ่งทำให้รหัสภาษาไทยที่ส่งมายัง Server ถูกตีความว่าเป็นรหัสแบบ ISO 8859-1 เมื่อถอดรหัสออกมา ภาษาไทยก็กลายเป็น ?

วิธีแก้ไข

  1. หากแน่ใจว่าข้อมูลที่ Request มาเป็นรหัสแบบใด เราก็สามารถกำหนดรหัสนั้นไว้ได้ด้วยคำสั่ง
          request.setCharacterEncoding(<Java Character Set>);
    
    โดยเขียนคำสั่งนี้ไว้ที่บรรทัดต้นๆก่อนที่จะทำงานกับข้อมูลนั้นๆ แต่วิธีการนี้ จะต้องเขียนคำสั่งนี้ทุกๆหน้าของ Web Application ซึ่งอาจจะไม่สะดวกนัก และหากต้องการเปลี่ยนแปลงรหัสเป็นอย่างอื่น ก็ต้องตามแก้ไขทุกๆหน้า หรืออาจจะเขียนเป็น including ก็น่าจะพอช่วยได้
  2. เขียนคำสั่งในข้อ 1 ไว้ในไฟล์หนึ่ง แล้วใช้คำสั่ง include จากทุกๆหน้า
  3. เพื่อให้สะดวกต่อการทำงาน เราสามารถสร้าง Filter ที่คอยกรอง Request ที่เข้ามา โดยตรวจสอบว่ามีการกำหนด Character Encoding ไว้แล้วหรือไม่ หากยังไม่กำหนด ก็กำหนดค่าให้ใหม่ได้ วิธีนี้เราจะสามารถกำหนดรหัสที่ต้องการให้กับ Filter ได้ใน WEB-INF/web.xml ไฟล์ เช่น
        public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
            throws IOException, ServletException {
    if (request.getCharacterEncoding() == null) {
    request.setCharacterEncoding(encoding); }
    chain.doFilter(request, response);
    }
    โดยที่เพิ่มเติม WEB-INF/web.xml ดังนี้
         <filter>
             <filter-name>Character Encoding Filter</filter-name>
             <filter-class>RequestCharacterEncodingFilter</filter-class>
                 <init-param>
                     <param-name>encoding</param-name>
                     <param-value>UTF-8</param-value>
                 </init-param>
         </filter>
         <filter-mapping>
             <filter-name>Character Encoding Filter</filter-name>
             <url-pattern>/*</url-pattern>
         </filter-mapping>
       

ตัวอย่าง

  1. ตัวอย่างการทดสอบปัญหา
  2. Source code ของคลาส RequestCharacterEncodingFilter

since September 2002
Web Counter by http://www.digits.com
Last updated : Monday, 20 March, 2006 11:23

Copyright © 2002-2004 Somchai LIMSIRORATANA. All rights reserved.