Текст UTF-8 искажается, когда форма публикуется как multipart/form-data

Я загружаю файл на сервер. HTML-форма для загрузки файла имеет 2 поля:

  1. Имя файла - текстовое поле HTML, где пользователь может дать имя на любом языке.
  2. Загрузка файла - файл HTMl, в котором пользователь может указать файл с диска для загрузки.

Когда форма отправлена, содержимое файла получено правильно. Однако когда имя файла (пункт 1 выше) читается, оно искажается. Символы ASCII отображаются правильно. Когда имя дается на каком-то другом языке (немецком, французском и т. Д.), Возникают проблемы.

В методе сервлета кодировка символов запроса установлена ​​в UTF-8. Я даже попытался сделать фильтр, как упомянуто - Как я могу сделать этот код для отправки текстовой области формы UTF-8 с работой jQuery/Ajax? - но это не похоже на работу. Только имя файла искажено.

Таблица MySQL, в которую входит имя файла, поддерживает UTF-8. Я дал случайные неанглийские символы, и они хранятся / отображаются правильно.

Используя Fiddler, я следил за запросом и все данные POST передаются правильно. Я пытаюсь определить, как / где данные могут быть искажены. Любая помощь будет оценена.

12 ответов

Решение

У меня была такая же проблема при использовании Apache commons-fileupload. Я не выяснил, что вызывает проблемы, особенно потому, что у меня есть кодировка UTF-8 в следующих местах: 1. Метатег HTML 2. Атрибут accept-charset формы 3. Фильтр Tomcat при каждом запросе, который устанавливает "UTF-8" кодирование

-> Мое решение заключалось в особом преобразовании строк из ISO-8859-1 (или любой другой кодировки по умолчанию для вашей платформы) в UTF-8:

new String (s.getBytes ("iso-8859-1"), "UTF-8");

надеюсь, это поможет

Редактировать: начиная с Java 8 вы также можете использовать следующее:

new String (s.getBytes (StandardCharsets.ISO_8859_1), StandardCharsets.UTF_8);

Просто используйте Apache Commons для загрузки библиотеки. добавлять URIEncoding="UTF-8" к соединителю Tomcat и используйте FileItem.getString("UTF-8") вместо FileItem.getString() без указания кодировки.

Надеюсь, это поможет.

Я застрял с этой проблемой и обнаружил, что это был заказ вызова

request.setCharacterEncoding("UTF-8");

это было причиной проблемы. Он должен вызываться перед любым вызовом метода request.getParameter(), поэтому я создал специальный фильтр для использования в верхней части цепочки фильтров.

http://www.ninthavenue.com.au/servletrequest-setcharactercoding-ignored

У меня была такая же проблема, и оказалось, что помимо указания кодировки в фильтре

request.setCharacterEncoding("UTF-8");
response.setCharacterEncoding("UTF-8");

необходимо добавить в форму "acceptcharset"

<form method="post" enctype="multipart/form-data" acceptcharset="UTF-8" > 

и запустить JVM с

-Dfile.encoding=UTF-8

Метатег HTML не требуется, если вы отправляете его в заголовке HTTP с использованием response.setCharacterEncoding().

Если кто-то натолкнулся на эту проблему при работе с веб-приложением Grails (или чистого Spring), вот пост, который мне помог:

http://forum.spring.io/forum/spring-projects/web/2491-solved-character-encoding-and-multipart-forms

Чтобы установить кодировку по умолчанию UTF-8 (вместо ISO-8859-1) для многочастных запросов, я добавил следующий код в resources.groovy (Spring DSL):

multipartResolver(ContentLengthAwareCommonsMultipartResolver) {
    defaultEncoding = 'UTF-8'
}

Я использую org.apache.commons.fileupload.servlet.ServletFileUpload.ServletFileUpload(FileItemFactory)и определение кодировки при считывании значения параметра:

List<FileItem> items = new ServletFileUpload(new DiskFileItemFactory()).parseRequest(request);

for (FileItem item : items) {
    String fieldName = item.getFieldName();

    if (item.isFormField()) {
        String fieldValue = item.getString("UTF-8"); // <-- HERE

Фильтр является ключевым для IE. Несколько других вещей, чтобы проверить;

Какая кодировка страницы и набор символов? Оба должны быть UTF-8

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>

Что такое набор символов в метатеге?

<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />

В строке подключения MySQL указано UTF-8? например

jdbc:mysql://127.0.0.1/dbname?requireSSL=false&useUnicode=true&characterEncoding=UTF-8

Я использую Primefaces с Glassfish и SQL Server.

в моем случае я создал Webfilter в бэк-энде, чтобы получать каждый запрос и конвертировать в UTF-8, например так:

package br.com.teste.filter;

import java.io.IOException;

import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.annotation.WebFilter;

@WebFilter(servletNames={"Faces Servlet"})
public class Filter implements javax.servlet.Filter {

    @Override
    public void destroy() {
        // TODO Auto-generated method stub

    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response,
            FilterChain chain) throws IOException, ServletException {
        request.setCharacterEncoding("UTF-8");
        chain.doFilter(request, response);      
    }

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        // TODO Auto-generated method stub      
    }

}

В представлении (.xhtml) мне нужно задать для формы параметра энктипа значение UTF-8, например @Kevin Rahe:

    <h:form id="frmt" enctype="multipart/form-data;charset=UTF-8" >
         <!-- your code here -->
    </h:form>  

Чтобы избежать ручного преобразования всех параметров запроса в UTF-8, вы можете определить метод, аннотированный с помощью @InitBinder в вашем контроллере:

@InitBinder
protected void initBinder(WebDataBinder binder) {
    binder.registerCustomEditor(String.class, new CharacterEditor(true) {
        @Override
        public void setAsText(String text) throws IllegalArgumentException {
            String properText = new String(text.getBytes(StandardCharsets.ISO_8859_1), StandardCharsets.UTF_8);
            setValue(properText);
        }
    });
}

Вышеупомянутое автоматически преобразует все параметры запроса в UTF-8 в контроллере, где он определен.

Вы также должны убедиться, что ваш фильтр кодирования (org.springframework.web.filter.CharacterEncodingFilter) в вашем файле web.xml сопоставлен перед многочастным фильтром (org.springframework.web.multipart.support.MultipartFilter).

У меня такая же проблема. Единственное решение, которое работало для меня, это добавление в multipartResoler в файле конфигурации Spring.

Я думаю, что опаздываю на вечеринку, но когда вы используете wildfly, вы можете добавить кодировку по умолчанию в standalone.xml. Просто найдите в standalone.xml для

<servlet-container name="default"> 

и добавьте кодировку следующим образом:

<servlet-container name="default" default-encoding="UTF-8">

Фильтр и настройка Tomcat для поддержки URI UTF-8 важны только в том случае, если вы передаете через строку запроса URL-адреса, как если бы вы использовали HTTP GET. Если вы используете POST со строкой запроса в теле HTTP-сообщения, важен тип содержимого запроса, и браузер должен установить тип содержимого в UTF-8 и отправить контент с этой кодировкой.

Единственный способ сделать это - сообщить браузеру, что вы можете принимать только UTF-8, устанавливая заголовок Accept-Charset при каждом ответе на "UTF-8;q=1,ISO-8859-1;q=0,6"., Это сделает UTF-8 лучшим качеством и кодировку по умолчанию, ISO-8859-1, приемлемой, но более низкого качества.

Когда вы говорите, что имя файла искажено, оно искажено в возвращаемом значении HttpServletRequest.getParameter?

Вы не используете UTF-8 для кодирования текстовых данных для HTML-форм. Стандарт html определяет две кодировки, и соответствующая часть этого стандарта находится здесь. "Старая" кодировка, чем обрабатывает ascii, является application/x-www-form-urlencoded. Новый, который работает правильно, является multipart/form-data.

В частности, объявление формы выглядит так:

 <FORM action="http://server.com/cgi/handle"
       enctype="multipart/form-data"
       method="post">
   <P>
   What is your name? <INPUT type="text" name="submit-name"><BR>
   What files are you sending? <INPUT type="file" name="files"><BR>
   <INPUT type="submit" value="Send"> <INPUT type="reset">
 </FORM>

И я думаю, что это все, что вам нужно беспокоиться - веб-сервер должен справиться с этим. Если вы пишете что-то, что непосредственно читает InputStream из веб-клиента, то вам нужно будет прочитать RFC 2045 и RFC 2046.

Другие вопросы по тегам