Как получить text / xml как UTF-8 из запроса multipart / form-data с помощью RESTeasy? - PullRequest
1 голос
/ 19 марта 2012

спасибо за ваш ответ, но использование InputStream вместо getBody (...) также не работает.Код ниже возвращает тот же результат, что и в моем исходном сообщении.

final InputStream inStream = fileUploadInput.getFormDataPart(searchedInput, InputStream.class, null);
// get bytes
final byte[] inBytes = new byte[1024];
final ByteArrayOutputStream outBytes = new ByteArrayOutputStream(inBytes.length);
int length = 0;
while((length = inStream.read(inBytes)) >= 0) {
    outBytes.write(inBytes, 0, length);
}
final byte[] rawInput = outBytes.toByteArray();

// get Encoding
final String asciiInput = new String(rawInput, ASCII);
final String utf8 = new String(rawInput, UTF8);
final String isoLatin1 = new String(rawInput, ISO8859_1);       
log.info("ASCII: " + ascii);
log.info("UTF8: " + utf8);
log.info("ISOLATIN1: " + isoLatin1);
return utf8;

ОРИГИНАЛЬНАЯ ПОЧТА:

Я хочу загрузить XML-файлы в кодировке UTF-8, используя приведенную ниже форму HTML, и прочитатьэто на сервере с использованием RESTEasy MultipartFormDataInput и кода Java, показанного ниже.На стороне сервера я, кажется, получаю содержимое файла (-ов) в кодировке ASCII, независимо от фактического кодирования загруженных файлов (которое является UTF-8) (доступ к нему описан ниже).Все символы, не входящие в набор символов ASCII, заменяются на ?.Как я могу получить 'text / xml' как UTF-8 из запроса 'multipart / form-data' с помощью RESTeasy?(Я знаю, что можно написать PreProcessor - Interceptor и получить туда необработанные байты, но я не могу использовать этот подход в своем приложении).

Форма загрузки:

<html>
<body>
    <h1>JAX-RS Upload Form</h1>

    <form action="http://.../upload" method="POST" enctype="multipart/form-data">

       <p>Select a file : <input type="file" name="upload"/></p>
       <input type="submit" value="Upload It" />

    </form>
</body>
</html>

Класс ресурса:

@Path("/upload")
@POST
@Consumes("multipart/form-data")
public Response createUploadTemplate(
        @Context HttpServletRequest req,
        MultipartFormDataInput formInput) {

    try {
        final String templateXml = getInput("upload", formInput);
        //...
    } catch (Exception e) {
        //...
    }
}

private static String getInput(final String searchedInput, final MultipartFormDataInput fileUploadInput) throws BadRequestException, IOException {

    try {
        final Map<String, List<InputPart>> inputToInputPart = fileUploadInput.getFormDataMap();

        if(inputToInputPart.containsKey(searchedInput)) {

            final StringBuilder builder = new StringBuilder();
            final List<InputPart> inputParts = inputToInputPart.get(searchedInput);

            for(InputPart inputPart : inputParts) {
                builder.append(inputPart.getBody(String.class,null));
            }

            return builder.toString();
        } else {
                throw new BadRequestException("The form send with the request does not contain an input element " + searchedInput + ".");
        }
    } catch(Exception e) {
        throw new BadRequestException("The file upload failed.", e);
    }
}

MessageBodyReader:

@Provider
@Consumes ("text/xml")
public class XmlStringReader implements MessageBodyReader<String> {
    private static Logger log = LoggerFactory.getLogger(UploadedXmlStringReader.class);

    private static final String ASCII = "ASCII";
    private static final String ISO8859_1 = "ISO8859_1";
    private static final String UTF8 = "UTF8";

    @Override
    public boolean isReadable(final Class<?> type,
                                final Type genericType,
                                final Annotation[] annotations,
                                final MediaType mediaType) {

        boolean result = type.equals(String.class) && MediaType.TEXT_XML_TYPE.equals(mediaType);
        log.info(MessageFormat.format("{0} == String.class && MediaType.TEXT_XML_TYPE == {1}: {2}", type, mediaType, result));
        return result;
    }

    @Override
    public String readFrom(final Class<String> type,
                                        final Type genericType,
                                        final Annotation[] annotations,
                                        final MediaType mediaType,
                                        final MultivaluedMap<String, String> httpHeaders,
                                        final InputStream entityStream) throws IOException, WebApplicationException {

        final byte[] inBytes = new byte[1024];
        final ByteArrayOutputStream outBytes = new ByteArrayOutputStream(inBytes.length);
        int length = 0;

        while((length = entityStream.read(inBytes)) >= 0) {
            outBytes.write(inBytes, 0, length);
        }

        final byte[] rawInput = outBytes.toByteArray();
        final String ascii = new String(rawInput, ASCII);

        final String utf8 = new String(rawInput, UTF8);
        final String isoLatin1 = new String(rawInput, ISO8859_1);       

        log.info("ASCII: " + ascii);
        log.info("UTF8: " + utf8);
        log.info("ISOLATIN1: " + isoLatin1);

        return utf8;
    }
}

Ответы [ 2 ]

4 голосов
/ 26 апреля 2013

Если в заголовке типа содержимого вашего HTTP-запроса не определена кодировка, resteasy предполагает 'charset = US-ASCII'. См. Org.jboss.resteasy.plugins.providers.multipart.InputPart:

/**
    * If there is a content-type header without a charset parameter, charset=US-ASCII
    * is assumed.
    * <p>
    * This can be overwritten by setting a different String value in
    * {@link org.jboss.resteasy.spi.HttpRequest#setAttribute(String, Object)}
    * with this ("resteasy.provider.multipart.inputpart.defaultCharset")
    * String`enter code here` as key. It should be done in a
    * {@link org.jboss.resteasy.spi.interception.PreProcessInterceptor}.
    * </p>
     */

Итак, в качестве обходного пути вы можете сделать следующее:

 @Provider
@ServerInterceptor
public class CharsetPreProcessInterceptor implements PreProcessInterceptor {

    @Override
    public ServerResponse preProcess(HttpRequest request, ResourceMethod method) throws Failure, WebApplicationException {
        request.setAttribute(InputPart.DEFAULT_CHARSET_PROPERTY, "charset=UTF-8");
        return null;
    }

}
0 голосов
/ 19 марта 2012

Обычно я не полагаюсь на getBody метод InputPart. На самом деле вы можете получить каждую часть в виде необработанного входного потока и прочитать данные в себе. Вместо того чтобы полагаться на каркас для преобразования содержимого в строку.

...