HTML:表单不发送 UTF-8 格式输入
Posted
技术标签:
【中文标题】HTML:表单不发送 UTF-8 格式输入【英文标题】:HTML : Form does not send UTF-8 format inputs 【发布时间】:2016-02-29 17:35:38 【问题描述】:我已经访问了有关 html 中的 UTF-8 编码的每一个问题,但似乎没有任何事情可以让它像预期的那样工作。
我添加了meta
标签:没有任何改变。
我在form
中添加了accept-charset
属性:没有任何改变。
JSP 文件
<%@ page pageEncoding="UTF-8" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<meta http-equiv="Content-Type" content="text/html;charset=UTF-8">
<title>Editer les sous-titres</title>
</head>
<body>
<form method="post" action="/Subtitlor/edit" accept-charset="UTF-8">
<h3 name="nameOfFile"><c:out value="$ nameOfFile "/></h3>
<input type="hidden" name="nameOfFile" id="nameOfFile" value="$ nameOfFile "/>
<c:if test="$ !saved ">
<input value ="Enregistrer le travail" type="submit" style="position:fixed; top: 10px; right: 10px;" />
</c:if>
<a href="/Subtitlor/" style="position:fixed; top: 50px; right: 10px;">Retour à la page d'accueil</a>
<c:if test="$ saved ">
<div style="position:fixed; top: 90px; right: 10px;">
<c:out value="Travail enregistré dans la base de donnée"/>
</div>
</c:if>
<table border="1">
<c:if test="$ !saved ">
<thead>
<th style="weight:bold">Original Line</th>
<th style="weight:bold">Translation</th>
<th style="weight:bold">Already translated</th>
</thead>
</c:if>
<c:forEach items="$ subtitles " var="line" varStatus="status">
<tr>
<td style="text-align:right;"><c:out value="$ line " /></td>
<td><input type="text" name="line$ status.index " id="line$ status.index " size="35" /></td>
<td style="text-align:right"><c:out value="$ lines[status.index].content "/></td>
</tr>
</c:forEach>
</table>
</form>
</body>
</html>
小服务程序
for (int i = 0 ; i < 2; i++)
System.out.println(request.getParameter("line"+i));
输出
Et ton père et sa soeur
Il ne sera jamais parti.
【问题讨论】:
看看那些答案httpservletrequest-utf-8-encoding 和request-getparameter-does-not-display-properly @SubOptimal 非常感谢,这行得通。但这会稍微减慢应用程序的速度,因为我的表单中有近 1000 个输入。您是否知道另一种方法可以做到这一点? 你试过了吗?这就是 Rails 所做的:***.com/questions/27338154/… @JacobWalker 因为我使用的是 POST,所以我认为它不起作用。 让我们continue this discussion in chat。 【参考方案1】:我添加了
meta
标签:没有任何改变。
当页面通过 HTTP 而不是例如通过 HTTP 提供时,它确实没有任何效果。来自本地磁盘文件系统(即页面的 URL 是 http://...
而不是例如 file://...
)。在 HTTP 中,将使用 HTTP 响应标头中的字符集。您已经将其设置如下:
<%@page pageEncoding="UTF-8"%>
这不仅会使用 UTF-8 写出 HTTP 响应,还会在 Content-Type
响应标头中设置 charset
属性。
webbrowser 将使用这个来解释响应并对任何 HTML 表单参数进行编码。
我在
form
中添加了accept-charset
属性:没有任何改变。
它只在 Microsoft Internet Explorer 浏览器中有效。即使那样,它也做错了。永远不要使用它。所有真正的网络浏览器都将使用响应的Content-Type
标头中指定的charset
属性。只要您不指定accept-charset
属性,即使MSIE 也会以正确的方式进行操作。如前所述,您已经通过pageEncoding
正确设置了它。
去掉meta
标签和accept-charset
属性。它们没有任何有用的效果,它们只会让你长期感到困惑,甚至在最终用户使用 MSIE 时让事情变得更糟。只要坚持pageEncoding
。除了在所有 JSP 页面上重复 pageEncoding
之外,您还可以在 web.xml
中全局设置它,如下所示:
<jsp-config>
<jsp-property-group>
<url-pattern>*.jsp</url-pattern>
<page-encoding>UTF-8</page-encoding>
</jsp-property-group>
</jsp-config>
如前所述,这将告诉 JSP 引擎使用 UTF-8 编写 HTTP 响应输出并将其设置在 HTTP 响应标头中。浏览器将使用相同的字符集对 HTTP 请求参数进行编码,然后再发送回服务器。
您唯一缺少的步骤是告诉服务器它必须使用 UTF-8 解码 HTTP 请求参数,然后才能返回 getParameterXxx()
调用。如何在全局范围内执行此操作取决于 HTTP 请求方法。鉴于您使用的是 POST 方法,使用以下自动挂钩所有请求的 servlet 过滤器类相对容易实现:
@WebFilter("/*")
public class CharacterEncodingFilter implements Filter
@Override
public void init(FilterConfig config) throws ServletException
// NOOP.
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException
request.setCharacterEncoding("UTF-8");
chain.doFilter(request, response);
@Override
public void destroy()
// NOOP.
就是这样。在 Servlet 3.0+(Tomcat 7 和更新版本)中,您不需要额外的 web.xml
配置。
您只需要记住,在第一次使用任何getParameterXxx()
方法获取POST 请求参数之前调用setCharacterEncoding()
方法非常重要。这是因为它们在第一次访问时只解析一次,然后缓存在服务器内存中。
例如以下顺序错误:
String foo = request.getParameter("foo"); // Wrong encoding.
// ...
request.setCharacterEncoding("UTF-8"); // Attempt to set it.
String bar = request.getParameter("bar"); // STILL wrong encoding!
在 servlet 过滤器中执行 setCharacterEncoding()
作业将保证它及时运行(至少在任何 servlet 之前)。
如果您想指示服务器也使用 UTF-8 解码 GET(而不是 POST)请求参数(您知道的那些在 URL 中 ?
字符之后看到的参数),那么您基本上需要在服务器端配置它。无法通过 servlet API 对其进行配置。例如,如果您使用 Tomcat 作为服务器,那么只需在 Tomcat 自己的 /conf/server.xml
的 <Connector>
元素中添加 URIEncoding="UTF-8"
属性即可。
如果您仍然在System.out.println()
调用的控制台输出中看到Mojibake,那么很有可能标准输出本身未配置为使用UTF-8。如何做到这一点取决于谁负责解释和呈现标准输出。如果您使用 Eclipse 作为 IDE,那么只需将 Window > Preferences > General > Workspace > Text File Encoding 设置为 UTF-8。
另见:
Unicode - How to get the characters right?【讨论】:
我挖了好几个小时才找到这个。为我解决了。谢谢! @BalusC,谢谢你的这篇文章。我已经按照您的建议实现了一个字符编码过滤器,但是当我解析来自多部分表单的请求时,我仍然必须使用formField.getString("UTF-8")
来获取正确的外来字符。我在这里错过了什么?
你可以试试下面的solution,没有过滤器,但它是Java(没有*.xml)
过滤器是解决方案。我将我的 mysql 连接设置为 jdbc:mysql://127.0.0.1:3306/database?useSSL=false&useUnicode=yes&characterEncoding=UTF-8 但表单总是传递错误的字符。非常感谢。【参考方案2】:
热身
让我首先说一个普遍的事实,我们都知道计算机除了位 - 0 和 1 什么都不理解。
现在,当您通过 HTTP 提交 HTML 表单并且值通过线路传输到目标服务器时,实际上会传递大量位 - 0 和 1。
在将数据发送到服务器之前,HTTP 客户端(浏览器或 curl 等)将使用某种编码方案对其进行编码,并希望服务器使用相同的方案对其进行解码,以便服务器确切知道客户端发送了什么。 在将响应发送回客户端之前,服务器将使用某种编码方案对其进行编码,并期望客户端使用相同的方案对其进行解码,以便客户端确切知道服务器发送了什么。对此的类比可以是 - 我正在给您发送一封信,并告诉您它是用英语还是法语或荷兰语写的,这样您就会得到我打算发送的准确信息你。在回复我的同时,您还会提到我应该阅读哪种语言。
重要的一点是,当数据离开客户端时,它会被编码,同样会在服务器端被解码,反之亦然。如果您不指定任何内容,则内容将按照application/x-www-form-urlencoded 进行编码,然后再从客户端传送到服务器端。
核心理念
阅读热身很重要。您需要做几件事来确保获得预期的结果。
在将数据从客户端发送到服务器之前设置正确的编码。 在服务器端设置了正确的解码和编码以读取请求并将响应写回客户端(这就是您没有得到预期结果的原因) 确保在所有地方都使用相同的编码方案,不应发生在客户端使用 ISO-8859-1 编码而在服务器使用 UTF-8 解码的情况,否则会出现错误(以我的类比,我用英语写你,你用法语阅读) 为您的日志查看器设置正确的编码,如果尝试使用 Windows 命令行或 Eclipse 日志查看器等验证使用日志。(这是导致您的问题的一个原因,但它不是主要原因,因为在首先,您从请求对象中读取的数据未正确解码。windows cmd 或 Eclipse 日志查看器编码也很重要,请阅读here)在将数据从客户端发送到服务器之前设置正确的编码
为了确保这一点,我们讨论了几种方法,但我会说使用HTTP Accept-Charset request-header field。根据您提供的代码 sn-p 您已经在使用并正确使用它,因此您在这方面做得很好。
有些人会说不要使用它或者它没有实现,但我非常谦虚地不同意他们。 Accept-Charset
是 HTTP 1.1 规范的一部分(我提供了链接),实现 HTTP 1.1 的浏览器将实现相同的功能。他们也可能争辩说使用Accept request-header field's“charset”属性但是
我为您提供所有数据和事实,而不仅仅是文字,但如果您不满意,请使用不同的浏览器进行以下测试。
在您的 HTML 表单和具有中文或高级法语字符的 POST/GET 表单中设置accept-charset="ISO-8859-1"
到服务器。
在服务器上使用 UTF-8 方案解码数据。
现在通过交换客户端和服务器编码重复相同的测试。
您将看到,您在服务器上始终无法看到预期的字符。但是,如果您将使用相同的编码方案,那么您将看到预期的字符。因此,浏览器确实实现了accept-charset
及其效果。
在服务器端设置正确的解码和编码以读取请求并将响应写回客户端
您可以通过多种方式来实现这一目标(有时可能需要根据特定场景进行一些配置,但以下解决了 95% 的情况,并且也适用于您的情况 )。例如:
-
使用字符编码过滤器设置请求和响应的编码。
在请求和响应时使用
setCharacterEncoding
使用-Dfile.encoding=utf8
等配置Web 或应用程序服务器以进行正确的字符编码。阅读更多here
等
我最喜欢的是第一个,它也能解决你的问题——“字符编码过滤器”,原因如下:
所有编码处理逻辑都集中在一处。 您可以通过配置获得所有的权力,在一个地方进行更改,如果每个人都满意的话。 在我设置字符编码之前,您不必担心其他代码可能正在读取我的请求流或刷新响应流。1。字符编码过滤器
您可以执行以下操作来实现自己的字符编码过滤器。如果您使用 Springs 等框架,则无需编写自己的类,只需在 web.xml 中进行配置
下面的核心逻辑与 Spring 所做的非常相似,除了它们所做的大量依赖项和 bean 感知之外。
web.xml(配置)
<filter>
<filter-name>EncodingFilter</filter-name>
<filter-class>
com.sks.hagrawal.EncodingFilter
</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
<init-param>
<param-name>forceEncoding</param-name>
<param-value>true</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>EncodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
EncodingFilter(字符编码实现类)
public class EncodingFilter implements Filter
private String encoding = "UTF-8";
private boolean forceEncoding = false;
public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain) throws IOException, ServletException
request.setCharacterEncoding(encoding);
if(forceEncoding) //If force encoding is set then it means that set response stream encoding as well ...
response.setCharacterEncoding(encoding);
filterChain.doFilter(request, response);
public void init(FilterConfig filterConfig) throws ServletException
String encodingParam = filterConfig.getInitParameter("encoding");
String forceEncoding = filterConfig.getInitParameter("forceEncoding");
if (encodingParam != null)
encoding = encodingParam;
if (forceEncoding != null)
this.forceEncoding = Boolean.valueOf(forceEncoding);
@Override
public void destroy()
// TODO Auto-generated method stub
2。 ServletRequest.setCharacterEncoding()
这与在字符编码过滤器中完成的代码基本相同,但不是在过滤器中执行,而是在您的 servlet 或控制器类中执行。
想法是在开始读取http请求流之前再次使用request.setCharacterEncoding("UTF-8");
设置http请求流的编码。
试试下面的代码,你会发现如果你没有使用某种过滤器来设置请求对象的编码,那么第一个日志将为 NULL,而第二个日志将为“UTF-8”。
System.out.println("CharacterEncoding = " + request.getCharacterEncoding());
request.setCharacterEncoding("UTF-8");
System.out.println("CharacterEncoding = " + request.getCharacterEncoding());
以下是setCharacterEncoding Java docs 的重要摘录。另一件需要注意的事情是你应该提供一个有效的编码方案,否则你会得到UnsupportedEncodingException
覆盖正文中使用的字符编码的名称 要求。 该方法必须在读取请求之前调用 使用 getReader() 读取参数或读取输入。否则,它没有 效果。
在需要时,我已尽力为您提供官方链接或 *** 接受的赏金答案,以便您建立信任。
【讨论】:
【参考方案3】:根据您发布的输出,该参数似乎是作为 UTF8 发送的,后来字符串的 unicode 字节被解释为 ISO-8859-1。
跟随 sn-p 演示您观察到的行为
String eGrave = "\u00E8"; // the letter è
System.out.printf("letter UTF8 : %s%n", eGrave);
byte[] bytes = eGrave.getBytes(StandardCharsets.UTF_8);
System.out.printf("UTF-8 hex : %X %X%n",
bytes[0], bytes[1], bytes[0], bytes[1]
);
System.out.printf("letter ISO-8859-1: %s%n",
new String(bytes, StandardCharsets.ISO_8859_1)
);
输出
letter UTF8 : è
UTF-8 hex : C3 A8
letter ISO-8859-1: è
对我来说,表单发送正确的 UTF8 编码数据,但后来这些数据不被视为 UTF8。
编辑其他一些可以尝试的点:
输出你的请求的字符编码
System.out.println(request.getCharacterEncoding())
强制使用UTF-8来检索参数(未经测试,只是一个想法)
request.setCharacterEncoding("UTF-8");
... request.getParameter(...);
【讨论】:
非常感谢,这有效。不幸的是,request.setCharacterEncoding 不起作用... 使用getBytes()
和new String()
来回按摩字符串的建议确实不是最理想的。这不是一个解决方案,而只是一个丑陋的解决方法。
嗨@BalusC 我的回答不是来回转换消息字符串的建议。而是... snippet demonstrates ... the form send the correct UTF8 encoded data, but later this data is not treated as UTF8
。而已。 request.setCharacterEncoding("UTF-8")
的提示并没有错,您在非常详细的答案中证明了这一点。它可能是在错误的时间调用的,因为我没有明确引用 API This method must be called prior to reading request parameters ... Otherwise, it has no effect.
。因为阅读 API 是不能被提及的。
@SubOptimal。您的回答帮助我隔离了问题。在尝试您的建议之前,我曾认为 POST 请求的编码存在问题。谢谢!【参考方案4】:
您可以尝试在 .jsp 上编写:
<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
pageEncoding="UTF-8"%>
问题解决了。
【讨论】:
【参考方案5】:您可以在您的 charset 中使用与 ISO 相关的字符串,并在您的 JSP 代码中使用 pageEncoding 定义。
如 charset="ISO-8859-1" 和 pageEncoding="ISO-8859-1"。
【讨论】:
【参考方案6】:tomcat 中有一个错误可能会困住你。第一个过滤器定义请求所基于的编码。
第一个过滤器后面的所有其他过滤器或 servlet 不能再更改请求的编码。
我认为这个错误将来不会被修复,因为当前的应用程序可能依赖于编码。
【讨论】:
【参考方案7】:resp.setContentType("text/html;charset=UT-8");
【讨论】:
以上是关于HTML:表单不发送 UTF-8 格式输入的主要内容,如果未能解决你的问题,请参考以下文章