RestEasy 文件上传 - 如何正确确定文件名编码?

Wil*_*con 3 java encoding multipartform-data resteasy

我正在使用下一个代码上传文件:

@Path("/files/")
@POST
@Consumes(MediaType.MULTIPART_FORM_DATA)
public OrderData uploadFile(MultipartFormDataInput input) {
    List<InputPart> parameterParts = input.getFormDataMap().get("Filename");
    String filename = parameterParts.get(0).getBody(String.class, null);
    ...
}
Run Code Online (Sandbox Code Playgroud)

它适用于拉丁字符,但我对西里尔文有问题(据我所知,因为 Java 默认将 rawpost 数据编码为 un​​icode)

如何正确确定编码并将数据从 post 编码为有效的 Java 字符串?

lef*_*loh 5

使用时,multipart/form-data您可以为每个部分指定一个带有编码的 Content-Type:

POST /some-resource HTTP/1.1
Content-Type: multipart/form-data; boundary=AaB03x

--AaB03x
Content-Disposition: form-data; name="file"; filename="file1.txt"
Content-Type: text/plain; charset=utf-8

... contents of file1.txt ...
--AaB03x--
Run Code Online (Sandbox Code Playgroud)

如果为每个部分添加此 Content-Type,它应该是开箱即用的(至少对于 RESTeasy 的当前版本 3.0.x)。您可以使用 RESTeasy 客户端对此进行测试:

WebTarget target = client.target("/some-resource");
MultipartFormDataOutput formData = new MultipartFormDataOutput();
formData.addFormData("file", fileContent, MediaType.TEXT_PLAIN_TYPE.withCharset("utf-8"));
Entity<MultipartFormDataOutput> entity = Entity.entity(formData, MediaType.MULTIPART_FORM_DATA);
Response response = target.request().post(entity);
Run Code Online (Sandbox Code Playgroud)

如果您的客户没有为您设置每个部分的 Content-Type 的可能性,您可以根据自定义标头更改默认编码(我正在添加一个修改后的代码示例,因为PreProcessInterceptor被标记为@deprecated):

@Provider
public class CharsetFilter implements ContainerRequestFilter {

    @Override
    public void filter(ContainerRequestContext requestContext) throws IOException {
        String charset = requestContext.getHeaderString("X-Charset");
        if (charset != null) {
            requestContext.setProperty(InputPart.DEFAULT_CHARSET_PROPERTY, charset);
        }
    }

}
Run Code Online (Sandbox Code Playgroud)

如果您使用的是纯 HTML 表单,您可以尝试添加<input type="hidden" name="_charset_" />到您的表单中。正如在multipart/form-data 编码算法中定义的那样,客户端应该用他正在使用的字符集填充这个字段。然后,您需要自己对 ResourceClass 中的内容进行编码:

@POST
@Path("/form")
@Consumes(MediaType.MULTIPART_FORM_DATA)
@Produces(MediaType.TEXT_PLAIN)
public Response uploadForm(MultipartFormDataInput input) throws IOException {
    String charset = input.getFormDataMap().get("_charset_").get(0).getBodyAsString();
    InputPart file = input.getFormDataMap().get("file").get(0);
    InputStream inputStream = file.getBody(InputStream.class, null);
    BufferedReader br = new BufferedReader(new InputStreamReader(inputStream, charset));
    String line;
    StringBuilder content = new StringBuilder();
    while ((line = br.readLine()) != null) {
        content.append(line);
    }
    return Response.ok(content).header("Content-Type", MediaType.TEXT_PLAIN_TYPE.withCharset(charset)).build();
}
Run Code Online (Sandbox Code Playgroud)