1

Sending a file with Czech characters UTF-8 encoded in filename (Žluťoučký kůň.txt), consumed by RESTEasy. But in java i always become US-ASCII filename (with is wrong of course)

HTML used to send file:

Select a file to upload: <br />
<form action="http://localhost/file/upload" method="post" enctype="multipart/form-data" accept-charset="UTF-8">
    <input type="file" name="file" size="50" />

    <input type="submit" value="Upload File" />
</form>

With is really sending:

------WebKitFormBoundaryAyBqNu6jIFHAB660
Content-Disposition: form-data; name="file"; filename="Žluťoučký kůň.txt"
Content-Type: text/plain

Used filters for obtain UTF-8 encoding:

@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain)
        throws IOException, ServletException {
    servletRequest.setCharacterEncoding("UTF-8");

 @Override
    public void filter(ContainerRequestContext requestContext) throws IOException {
        requestContext.setProperty(InputPart.DEFAULT_CONTENT_TYPE_PROPERTY, "*/*; charset=UTF-8");
        requestContext.setProperty(InputPart.DEFAULT_CHARSET_PROPERTY, "UTF-8");

Java code to read multipart:

 public List<CaseFile> uploadFile(MultipartFormDataInput input, long caseId) {
        MultipartFormDataOutput mdo = new MultipartFormDataOutput();
    Map<String, List<InputPart>> uploadForm = input.getFormDataMap();

    for (List<InputPart> inputParts : uploadForm.values()) {

        for (InputPart inputPart : inputParts) {
            try {

                // Retrieve headers, read the Content-Disposition header to obtain the original name of the file
                MultivaluedMap<String, String> headers = inputPart.getHeaders(); //here are all headers in US-ASCII

and header contain:

form-data; name="file"; filename="??lu??ou??k?? k????.txt"

Pavel Hora
  • 143
  • 1
  • 11
  • Please clarify "//here are all headers in US-ASCII". – Alastair McCormack Mar 15 '16 at 10:55
  • How are you viewing the headers? It's possible that your output stream doesn't support those characters. Please hexify your response in UTF-8, using http://stackoverflow.com/questions/923863/converting-a-string-to-hexadecimal-in-java – Alastair McCormack Mar 15 '16 at 13:08
  • No, i have already tried such conversion - its really US-ASCII only – Pavel Hora Mar 16 '16 at 09:04
  • Sounds like you know it all already! Perhaps you've overlooked: [How can I get resteasy MultipartFormDataInput to decode strings using UTF-8?](http://stackoverflow.com/questions/11215733/how-can-i-get-resteasy-multipartformdatainput-to-decode-strings-using-utf-8) – Alastair McCormack Mar 16 '16 at 09:17
  • I want to cry with happiness. The hack with reflection helps me. `Field f = inputPart.getClass().getDeclaredField("bodyPart"); f.setAccessible(true); BodyPart bodyPart = (BodyPart) f.get(inputPart); Header header = bodyPart.getHeader(); ... ` – Pavel Hora Mar 16 '16 at 17:01
  • I presume you mean this answer: http://stackoverflow.com/a/12512798/1554386 I notice it doesn't have any votes. I notice the answer has 0 votes so please up-vote the answer so people know it's good – Alastair McCormack Mar 16 '16 at 17:40

1 Answers1

2

i use wildfly 9 with resteasy. The code above result in class cast exception for me. The code below solve my problem:

        Field field = inputPart.getClass().getDeclaredField("bodyPart");
        field.setAccessible(true);
        Object bodyPart = field.get(inputPart);
        Method methodBodyPart = bodyPart.getClass().getMethod("getHeader", new Class[]{});
        Iterable iterable = (Iterable)methodBodyPart.invoke(bodyPart, new Class[]{});
        Object[] content = IteratorUtils.toArray(iterable.iterator());
        Method methodContent = content[0].getClass().getMethod("getRaw", new Class[]{});

        String[] contentDisposition = methodContent.invoke(content[0], new Class[]{}).toString().split(";");

        for (String filename : contentDisposition) {
            if ((filename.trim().startsWith("filename"))) {

                String[] name = filename.split("=");

                String finalFileName = name[1].trim().replaceAll("\"", "");
                return finalFileName;
            }
        }
Paulo Roberto
  • 261
  • 2
  • 7