是否可以从okhttp3客户端发送UTF-8字符?
对于以下字符串:
String fileName = "3$ Mù F'RANçé_33902_Country_5_202105";
String contentDisposition = "attachment;filename=" + "\"" + fileName + "\"";
我已经尝试过(对于contentDissition标头):
Headers headers = new Headers.Builder()
.addUnsafeNonAscii("Content-Disposition", contentDisposition)
.add("Authorization", bearer)
.add("Content-type", "application/octet-stream")
.build();
Request request = new Request.Builder()
.headers(headers)
.post(requestBody)
.url(urlAddress)
.build();
但服务器收到:3$MÃF'RANçÃ33902_Country_5_202105
此请求发送给公司合作伙伴,因此我无法访问后端。
应用程序/八位流
是后端需要的。
身体是这样产生的:
byte[] data = FileUtils.readFileToByteArray(file);
RequestBody requestBody = RequestBody.create(data);
这对邮递员来说非常好。
完整的MVCE(不能包含文件和后端信息,但它以前崩溃过,所以您可以直接启动这段代码,它应该会抛出错误):
public class App
{
public static void main( String[] args ) throws IOException
{
OkHttpClient client = new OkHttpClient().newBuilder()
.build();
MediaType mediaType = MediaType.parse("application/octet-stream");
RequestBody body = RequestBody.create(mediaType, "");
Request request = new Request.Builder()
.url("xxxx")
.method("POST", body)
.addHeader("Content-Type", "application/octet-stream")
.addHeader("content-disposition", "attachment;filename=\"3$ Mù F'RANçé_33902_Country_5_202105.csv\"")
.addHeader("Authorization", "Bearer xxxxx")
.addHeader("Cookie", "xxxxxx")
.build();
Response response = client.newCall(request).execute();
}
}
收到错误:java。lang.IllegalArgumentException:内容处置值:附件中25处的意外字符0xf9;filename=“3$MùF'RANç33902_Country_5_202105.csv”
okhttp版本:5.0.0-alpha。2
我错过什么了吗?
谢啦
HTTP头的默认字符集是ISO-8859-1。然而,RFC 6266描述了如何在内容处置
标题中对文件名进行编码。基本上,您可以指定字符集名称,然后对UTF-8字符进行百分比编码。使用以fileName*=utf-8''开头的参数,而不是
fileName=“my simple fileName”
,比如
import java.net.URLEncoder;
// ...
String fileName = "3$ Mù F'RANçé_33902_Country_5_202105";
String contentDisposition = "attachment;filename*=utf-8''" + encodeFileName(fileName);
// ...
private static String encodeFileName(String fileName) throws UnsupportedEncodingException {
return URLEncoder.encode(fileName, "UTF-8").replace("+", "%20");
}
如果想避免使用Guava、Spring的
ContentDisposition
类或任何其他库,只需使用JRE类,那么使用URL编码器然后修改“”的结果是我在这里发现的一个廉价技巧。
更新:这是一个完整的MCVE,展示了如何将UTF-8字符串作为帖子正文和内容处置文件名发送。演示服务器展示了如何手动解码该报头——通常HTTP服务器应该自动解码。
Maven POM显示使用的依赖项:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.example</groupId>
<artifactId>SO_Java_OkHttp3SendUtf8_70804280</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<maven.compiler.source>11</maven.compiler.source>
<maven.compiler.target>11</maven.compiler.target>
</properties>
<dependencies>
<dependency>
<groupId>com.squareup.okhttp3</groupId>
<artifactId>okhttp</artifactId>
<version>4.9.3</version>
</dependency>
<dependency>
<groupId>org.nanohttpd</groupId>
<artifactId>nanohttpd</artifactId>
<version>2.3.1</version>
</dependency>
</dependencies>
</project>
OkHttp演示客户端:
import okhttp3.Headers;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;
import java.io.IOException;
import java.net.URL;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.Objects;
public class Client {
public static void main(String[] args) throws IOException {
String fileName = "3$ Mù F'RANçé_33902_Country_5_202105";
String contentDisposition = "attachment;filename*=utf-8''" + encodeFileName(fileName);
RequestBody requestBody = RequestBody.create(fileName.getBytes(StandardCharsets.UTF_8));
Headers headers = new Headers.Builder()
.add("Content-Disposition", contentDisposition)
.add("Content-type", "application/octet-stream; charset=utf-8")
.build();
Request request = new Request.Builder()
.headers(headers)
.post(requestBody)
.url(new URL("http://localhost:8080/"))
.build();
OkHttpClient client = new OkHttpClient();
Response response = client.newCall(request).execute();
System.out.println(Objects.requireNonNull(response.body()).string());
}
private static String encodeFileName(String fileName) {
return URLEncoder.encode(fileName, StandardCharsets.UTF_8).replace("+", "%20");
}
}
NanoHTTPD演示服务器:
import fi.iki.elonen.NanoHTTPD;
import java.io.IOException;
import java.net.URLDecoder;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.Map;
public class Server extends NanoHTTPD {
public Server() throws IOException {
super(8080);
start(NanoHTTPD.SOCKET_READ_TIMEOUT, false);
System.out.println("\nRunning! Point your browsers to http://localhost:8080/ \n");
}
public static void main(String[] args) throws IOException {
new Server();
}
private static final String UTF_8_FILE_NAME_PREFIX = ";filename*=utf-8''";
private static final int UTF_8_FILE_NAME_PREFIX_LENGTH = UTF_8_FILE_NAME_PREFIX.length();
@Override
public Response serve(IHTTPSession session) {
try {
Map<String, String> files = new HashMap<>();
session.parseBody(files);
String postBody = files.get("postData");
String contentDisposition = session.getHeaders().get("content-disposition");
String fileName = decodeFileName(
contentDisposition.substring(
contentDisposition.indexOf(UTF_8_FILE_NAME_PREFIX) + UTF_8_FILE_NAME_PREFIX_LENGTH
)
);
System.out.println("POST body: " + postBody);
System.out.println("Content disposition: " + contentDisposition);
System.out.println("UTF-8 file name: " + fileName);
return newFixedLengthResponse(postBody + "\n" + fileName);
}
catch (IOException | ResponseException e) {
e.printStackTrace();
return newFixedLengthResponse(e.toString());
}
}
private static String decodeFileName(String fileName) {
return URLDecoder.decode(fileName.replace("%20", "+"), StandardCharsets.UTF_8);
}
}
如果先运行服务器,然后运行客户端,您将在服务器控制台上看到:
Running! Point your browsers to http://localhost:8080/
POST body: 3$ Mù F'RANçé_33902_Country_5_202105
Content disposition: attachment;filename*=utf-8''3%24%20M%C3%B9%20F%27RAN%C3%A7%C3%A9_33902_Country_5_202105
UTF-8 file name: 3$ Mù F'RANçé_33902_Country_5_202105
在客户端控制台上,您会看到:
3$ Mù F'RANçé_33902_Country_5_202105
3$ Mù F'RANçé_33902_Country_5_202105
我正在Ubuntu中运行httpd+mod_jk+2个tomcat服务器。当我以非拉丁语言提交表单时,我会在DB中得到垃圾。如果我通过Tomcat提交相同的表单,直接绕过httpd,那么一切看起来都很好。以下是我的配置: /ETC/APACHE2/CONF.D/CHARSET: Tomcat1: Tomcat2: JDBC连接: jdbc:mysql://localhost:3306/myapp?
在Flutter中,无论我尝试解码什么json文件,我都会得到上面相同的标题错误。最初我认为这是我的项目,但在开始一个新的模板Flutter项目后,我仍然收到同样的错误。我有json文件在我的根文件夹,并已将它们添加到pubspec.yaml文件: 主要的目前的dart代码: 我已经在多个测试站点验证了我的json数据,并在Flutter文档中尝试了各种方法。Json数据:
我试图反序列化JSON的格式 类类型 因为我有一个映射类型,所以我添加了一个键反序列化器来反序列化 但是当我尝试反序列化时,我得到了一个异常 这是因为它遇到了在中,它在那里中断。如果我将整个键放在双引号中,它会将整个键传递给我的反序列化程序。 有没有一种方法,我可以迫使它转义char,而不必把整个关键与引号。
问题内容: 我在字符串列表的json.Marshal上得到这个: 原因很明显,但是如何在Go中删除/替换这样的字符串?我一直在阅读docst 和包,似乎没有明显/快速的方法。 例如,在Python中,您可以使用一些方法删除无效字符,将其替换为指定字符或严格设置,这会导致无效字符的异常。如何在Go中做等效的事情? 更新:我的意思是得到异常的原因(紧急?)-json.Marshal期望有效的UTF-8
问题内容: 网络服务器使用utf-8编码提供响应,所有文件都使用utf-8编码保存,我所知的所有设置都已设置为utf-8编码。 这是一个快速程序,用于测试输出是否有效: 该程序的输出为: 呈现为: 我可能做错了什么?我必须告诉DomDocument正确处理utf-8的具体程度是多少? 问题答案: 需要一个HTML字符串。 HTML 根据其规范使用默认的编码(ISO拉丁字母1号)。那是因为更长,请参
问题内容: 我想测试我的代码的Unicode处理。有什么我可以放入random.choice()从整个Unicode范围中选择的东西,最好不是外部模块吗?Google和StackOverflow似乎都没有答案。 编辑:看起来这比预期的要复杂,所以我将重新表述这个问题- 以下代码足以生成Unicode中的所有有效非控制字符吗? 问题答案: 您可以使用Markus Kuhn 提供的UTF-8压力测试。