Javascript JS套接字未正确传递特殊字符
所以,我经常看到这个问题,但公认的答案对我来说并不适用。我正在开发一个类似聊天室的网站,虽然它在大多数情况下都运行良好(我知道我的代码中还有一些小问题,但它们不是问题的一部分),但每当涉及到JS文件和使用套接字时,我都会遇到字符编码问题。我现在将发布我的HTML和JS文件: HTML:Javascript JS套接字未正确传递特殊字符,javascript,html,flask,encoding,Javascript,Html,Flask,Encoding,所以,我经常看到这个问题,但公认的答案对我来说并不适用。我正在开发一个类似聊天室的网站,虽然它在大多数情况下都运行良好(我知道我的代码中还有一些小问题,但它们不是问题的一部分),但每当涉及到JS文件和使用套接字时,我都会遇到字符编码问题。我现在将发布我的HTML和JS文件: HTML: {% extends "layout.html" %} {% block heading %} <meta charset="UTF-8"> &
{% extends "layout.html" %}
{% block heading %}
<meta charset="UTF-8">
<script type="text/javascript" src="{{ url_for('static', filename='js/chatroom.js') }}"></script>
<link rel="stylesheet" href="{{ url_for('static', filename='css/chatroom.css') }}">
{% endblock %}
{% block body %}
The Chatroom name is <span id="chatroom">{{ chatroom }}</span> and it's code is <span id="code">{{ code }}</span>
<div id="messages">
{% for message in messages %}
{% if message.author == online_user %}
<div class="own">{{ message.message }}</div>
{% else %}
<div class="other"><strong>{{ message.author }}</strong><br> {{ message.message }}</div>
{% endif %}
{% endfor %}
</div>
<textarea id="message" rows=5 cols=50></textarea>
<input type="button" id="send" value="Send">
{% endblock %}
document.addEventListener('DOMContentLoaded', () => {
var socket = io.connect(location.protocol + '//' + document.domain + ':' + location.port);
socket.on('connect', () => {
document.querySelector('#send').onclick = () => {
const message = document.querySelector('#message').value;
socket.emit('send message', {'chatroom': {'code':document.querySelector('#code').innerHTML, 'name': document.querySelector('#chatroom').innerHTML}, 'message': message});
};
});
socket.on('broadcast message', data => {
if (data.message['chatroom']['code'] == document.querySelector('#code').innerHTML) {
const msg = document.createElement('div');
if (data.message['author'] == document.getElementById('current_user').innerHTML)
msg.innerHTML = data.message['message'];
else
msg.innerHTML = `${data.message['author']}: ${data.message['message']}`
document.querySelector('#messages').append(msg);
var listlen = document.getElementById('messages').getElementsByTagName('div').length;
while (listlen > 100) {
var msglist = document.getElementById('messages');
msglist.removeChild(msglist.childNodes[0]);
var listlen = document.getElementById('messages').getElementsByTagName('div').length;
};
};
});
});
现在,当不涉及JS文件和套接字时(例如,如果我登录到该站点),编码工作正常。但是,当textarea包含特殊字符如Á(我将在两个字段中使用单词Ángel作为示例)时,一旦我点击send按钮(而不是之前),输出是错误的
当前输出:{'chattroom':{'code':'ouAY7mxCvhXb','name':'UTF'},'author':'engel','message':'Ã\x81ngel'}
预期输出:{'chattroom':{'code':'ouAY7mxCvhXb','name':'UTF'},'author':'engel','message':'engel'}
其他问题的公认答案是在我的HTML中添加
行,但我现在感到困惑,因为它不起作用。我也检查了,我的JS文件也正确地编码为UTF-8
编辑:
{% extends "layout.html" %}
{% block heading %}
<meta charset="UTF-8">
<script type="text/javascript" src="{{ url_for('static', filename='js/chatroom.js') }}"></script>
<link rel="stylesheet" href="{{ url_for('static', filename='css/chatroom.css') }}">
{% endblock %}
{% block body %}
The Chatroom name is <span id="chatroom">{{ chatroom }}</span> and it's code is <span id="code">{{ code }}</span>
<div id="messages">
{% for message in messages %}
{% if message.author == online_user %}
<div class="own">{{ message.message }}</div>
{% else %}
<div class="other"><strong>{{ message.author }}</strong><br> {{ message.message }}</div>
{% endif %}
{% endfor %}
</div>
<textarea id="message" rows=5 cols=50></textarea>
<input type="button" id="send" value="Send">
{% endblock %}
document.addEventListener('DOMContentLoaded', () => {
var socket = io.connect(location.protocol + '//' + document.domain + ':' + location.port);
socket.on('connect', () => {
document.querySelector('#send').onclick = () => {
const message = document.querySelector('#message').value;
socket.emit('send message', {'chatroom': {'code':document.querySelector('#code').innerHTML, 'name': document.querySelector('#chatroom').innerHTML}, 'message': message});
};
});
socket.on('broadcast message', data => {
if (data.message['chatroom']['code'] == document.querySelector('#code').innerHTML) {
const msg = document.createElement('div');
if (data.message['author'] == document.getElementById('current_user').innerHTML)
msg.innerHTML = data.message['message'];
else
msg.innerHTML = `${data.message['author']}: ${data.message['message']}`
document.querySelector('#messages').append(msg);
var listlen = document.getElementById('messages').getElementsByTagName('div').length;
while (listlen > 100) {
var msglist = document.getElementById('messages');
msglist.removeChild(msglist.childNodes[0]);
var listlen = document.getElementById('messages').getElementsByTagName('div').length;
};
};
});
});
我将为套接字添加服务器端代码,因为这可能有助于更好地理解输出。如图所示,编码问题只发生在我从数据传递过来的内容上(这只会在消息内容和聊天室名称上出错,因为聊天室代码是自动生成的,从不包含特殊字符)
如果有人遇到这个问题,我找到了一种解决方法,以备将来参考。我没有通过套接字传递原始消息并期望程序使用meta标记自动将其转换为UTF-8,而是通过在JS文件上添加编码函数并将其应用于消息内容来对其进行编码
function encode_utf8(s) {
return encodeURIComponent(s);
}
JS文件的前4行现在看起来是这样的:const message=encode_utf8(document.querySelector('#message').value)代码>
这允许我以后端服务器可以正确解码的方式发送它,这样它就可以通过使用urllib.parse
库的unquote\u plus
返回预期的输出
@socketio.on("send message")
def send_message(data):
data['message'] = data['message'].strip()
print(data)
if len(data["message"]) > 0:
message = {'chatroom': data['chatroom'], 'author': session['username'], 'message': urllib.parse.unquote_plus(data['message'])} # <-- Modified line
print(message)
stored_messages.append(message)
local_messages.append(message)
emit("broadcast message", {'message': message}, broadcast=True)
@socketio.on(“发送消息”)
def发送消息(数据):
数据['message']=数据['message'].strip()
打印(数据)
如果len(数据[“消息])>0:
message={'chatroom':data['chatroom'],'author':session['username'],'message':urllib.parse.unquote_plus(data['message'])}这只是一个猜测,但是您的layout.html
是否同时定义了head
和heading
块?如果是这样,您的子版面应该将meta
标记放在head
块下(或者直接将meta
标记放在layout.html
中)。让我知道这是否有帮助,我会把它作为一个答案发布。谢谢你的回复!标题
块是我的版面上标题
的一部分。我尝试将meta
移动到布局中,但问题仍然存在。我也会将服务器端代码添加到原始帖子中,看看那里是否有问题。只是为了确保:当页面呈现时,
是否嵌套在
下?是的,它现在是head标记内的第一行,无论是在文件中还是呈现时。