Java 如何抑制在okhttp中自动添加到内容类型的字符集
考虑以下代码:Java 如何抑制在okhttp中自动添加到内容类型的字符集,java,google-cloud-storage,okhttp,pre-signed-url,Java,Google Cloud Storage,Okhttp,Pre Signed Url,考虑以下代码: OkHttpClient client = new OkHttpClient(); MediaType mediaType = MediaType.parse("text/plain; charset=utf-8"); // [A] RequestBody body = RequestBody.create(mediaType, media); String[] aclHeader = "x-goog-acl:public-read".split
OkHttpClient client = new OkHttpClient();
MediaType mediaType = MediaType.parse("text/plain; charset=utf-8"); // [A]
RequestBody body = RequestBody.create(mediaType, media);
String[] aclHeader = "x-goog-acl:public-read".split(":");
Request request = new Request.Builder()
.addHeader("Content-Type", "text/plain") // [B]
.addHeader(aclHeader[0], aclHeader[1])
.url(url)
.put(body)
.build();
Response response = client.newCall(request).execute();
/**
* Returns a new request body that transmits this string. If [contentType] is non-null and lacks
* a charset, this will use UTF-8.
*/
@JvmStatic
@JvmName("create")
fun String.toRequestBody(contentType: MediaType? = null): RequestBody {
var charset: Charset = UTF_8
var finalContentType: MediaType? = contentType
if (contentType != null) {
val resolvedCharset = contentType.charset()
if (resolvedCharset == null) {
charset = UTF_8
finalContentType = "$contentType; charset=utf-8".toMediaTypeOrNull()
} else {
charset = resolvedCharset
}
}
val bytes = toByteArray(charset)
return bytes.toRequestBody(finalContentType, 0, bytes.size)
}
我正在从一个客户端访问GCS,使用一个先前签名的URL
问题:okhttp似乎也将为正文[A]声明的字符集添加到URL中(至少对于文本/纯文本),即使它没有在[B]中声明。这弄乱了我的签名URL,GCS返回403禁止
- 如果我从[A]中删除字符集,它仍然会被添加
- 如果我在签名之前将字符集添加到签名的URL中,它会工作,GCS返回200 OK
String[] aclHeader = "x-goog-acl:public-read".split(":");
StatusLine statusLine = Request
.Put(url)
.addHeader("Content-Type", "text/plain")
.addHeader(aclHeader[0], aclHeader[1])
.bodyByteArray(media)
.execute().returnResponse().getStatusLine();
有没有一种方法可以抑制okhttp中的行为,即添加内容类型或在正文中冗余传输内容类型?我找到了解决方案:
以下是罪魁祸首:
RequestBody body = RequestBody.create(mediaType, media);
创建有3个媒体签名:
- 串
- 字节[]
- 文件
[愚蠢的我-为了简单起见,我在测试期间给了它一个字符串,因为我不关心正文;-(]当您创建requestbody时,只需将内容类型设置为“null”,并添加标题手册,如下所示:
OkHttpClient client = new OkHttpClient();
RequestBody body = RequestBody.create('your media string', null);
String[] aclHeader = "x-goog-acl:public-read".split(":");
Request request = new Request.Builder()
.addHeader("Content-Type", "text/plain") // [B]
.addHeader(aclHeader[0], aclHeader[1])
.url(url)
.put(body)
.build();
Response response = client.newCall(request).execute();
因为当我在RequestBody.kt中阅读okhttp源代码时,我发现以下代码:
OkHttpClient client = new OkHttpClient();
MediaType mediaType = MediaType.parse("text/plain; charset=utf-8"); // [A]
RequestBody body = RequestBody.create(mediaType, media);
String[] aclHeader = "x-goog-acl:public-read".split(":");
Request request = new Request.Builder()
.addHeader("Content-Type", "text/plain") // [B]
.addHeader(aclHeader[0], aclHeader[1])
.url(url)
.put(body)
.build();
Response response = client.newCall(request).execute();
/**
* Returns a new request body that transmits this string. If [contentType] is non-null and lacks
* a charset, this will use UTF-8.
*/
@JvmStatic
@JvmName("create")
fun String.toRequestBody(contentType: MediaType? = null): RequestBody {
var charset: Charset = UTF_8
var finalContentType: MediaType? = contentType
if (contentType != null) {
val resolvedCharset = contentType.charset()
if (resolvedCharset == null) {
charset = UTF_8
finalContentType = "$contentType; charset=utf-8".toMediaTypeOrNull()
} else {
charset = resolvedCharset
}
}
val bytes = toByteArray(charset)
return bytes.toRequestBody(finalContentType, 0, bytes.size)
}
是的。OkHttp需要决定如何将字符串转换为字节,当它这样做时,它会在字符集中记录该决定。顺便问一下,为什么不指定字符集?服务器可能会使用启发式进行猜测,它可能会猜错!我明白,是的。我没有指定字符集,因为我认为图像是二进制的,而我只使用了Strin我不在乎内容,所以我也不在乎字符集。但我承认这是有道理的。你能给我举几个例子吗?我不知道如何使用它。