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

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

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

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

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

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

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

Ответы

Ответ 1

У меня была такая же проблема при использовании 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);

Ответ 2

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

Надеюсь на эту помощь.

Ответ 3

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

request.setCharacterEncoding("UTF-8");

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

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

Ответ 4

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

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().

Ответ 5

Если кто-то натолкнулся на эту проблему при работе с веб-приложением 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'
}

Ответ 6

Я использую 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

Ответ 7

Фильтр является ключевым для 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

Ответ 8

Я использую Primefaces со стекловолокном и 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) мне нужно установить форму пареметра enctype в UTF-8, например @Kevin Rahe:

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

Ответ 9

Объект фильтра и настройка Tomcat для поддержки URI UTF-8 важны только в том случае, если вы передаете строку запроса URL-адреса, как в случае с GET HTTP. Если вы используете 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?

Ответ 10

У меня такая же проблема. Единственное решение, которое работало для меня, это добавление <property = "defaultEncoding" value = "UTF-8"> в multipartResoler в файле конфигурации Spring.

Ответ 11

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

Ответ 12

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

<servlet-container name="default"> 

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

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

Ответ 13

Чтобы избежать преобразования всех параметров запроса вручную в 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 в контроллере, где он определен.

Ответ 14

Вы не используете 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.