我有一个表单,用户可以在其中将字符串输入文本区域。然后,该字符串将用作对外部服务的 api 调用中的查询参数。
服务对此特定参数的长度有限制;不能超过512个字符,需要进行URL编码。
虽然我可以将文本区域的最大长度设置为 512,但这仍然会导致编码时的查询参数超出最大长度,因为任何空格都将被编码为
%20
等。
目前我正在做以下事情:
// 512 character long search text given by user.
$dummySearchString = 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Quisque tincidunt, nunc a consequat luctus, eros leo interdum nisl, vel convallis felis sapien eu nisl. Fusce ut viverra libero. Mauris non nulla sed elit varius volutpat. Sed in malesuada lacus. Nullam vel odio sagittis, ullamcorper mauris vel, scelerisque odio. Aliquam erat volutpat. Sed ut facilisis sapien, a rutrum sapien. Proin nec urna at ante egestas luctus sed in eros. Fusce accumsan odio sed ornare posuere. Ut consectetur arcu sed bibendum pretium. Integer tristique orci eget velit dictum, eu tristique justo aliquet. Praesent finibus egestas enim, vulputate varius tortor consequat id.';
// Encode the string, we first trim of any blank spaces from start and end.
$encodedQueryString = rawurlencode(trim($dummySearchString));
// Check the length and trim if exceeding 512 characters.
$encodedQueryString = substr($encodedString, 0, 512);
// Make http request.
$response = $this->client->request('GET', 'https://example.com/api/v1/search', [
'query' => [
'q' => rawurldecode($encodedQueryString),
],
]);
上述方法在大多数情况下都有效,但仍然可能存在实体中间修剪等问题。
在这种情况下,确保在文本区域中输入的文本可用作查询参数的最佳解决方案是什么?
一种可能性是逐个字符地对字符串进行编码,直到达到限制,并且如果编码字符会被切断,则不要添加编码字符。
但是,如果字符串包含多字节字符,这可能会很棘手。 PHP 不是我的强项,但我相信正确获取多字节字符的正确方法是使用
mb_substr
。
您可以连续检查编码字符串的长度,并相应地启用/禁用表单提交。下面是一个快速但肮脏的实现:
const txt = 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Quisque tincidunt, nunc a consequat luctus, eros leo interdum nisl, vel convallis felis sapien eu nisl. Fusce ut viverra libero. Mauris non nulla sed elit varius volutpat. Sed in malesuada lacus. Nullam vel odio sagittis, ullamcorper mauris vel, scelerisque odio. Aliquam erat volutpat. Sed ut facilisis sapien, a rutrum sapien. Proin nec urna at ante egestas luctus sed in eros. Fusce accumsan odio sed ornare posuere. Ut consectetur arcu sed bibendum pretium. Integer tristique orci eget velit dictum, eu tristique justo aliquet. Praesent finibus egestas enim, vulputate varius tortor consequat id.';
const [query,free,submit]=["query","free","submit"].map(id=>document.getElementById(id));
query.value=txt.slice(0,385);
query.addEventListener("input",ev=>{
let n=free.textContent=512-encodeURIComponent(query.value.trim()).length;
submit.disabled=n<0?true:false;
})
<form>
<textarea id="query" cols="60" rows="6"></textarea><br>
(space for <span id="free"></span> more characters.)<br>
<button id="submit**strong text**">submit</button>
</form>