Как я могу сказать groovy / grails не пытаться «перекодировать» двоичные данные? (Пересмотренное название) - PullRequest
1 голос
/ 05 апреля 2010

У меня есть приложение Groovy / Grails, которое должно обслуживать изображения

На моем устройстве dev работает нормально, изображение возвращается правильно. Вот начало возвращенного JPEG, как видно из od -cx

0000000  377 330 377 340  \0 020   J   F   I   F  \0 001 001 001 001   ,
             d8ff    e0ff    1000    464a    4649    0100    0101    2c01

но на производственной коробке впереди есть какой-то мусор, и d8ff e0ff до 1000 отсутствует

0000000    �  **  **   �  **  **   �  **  **   �  **  **  \0 020   J   F
             bfef    efbd    bdbf    bfef    efbd    bdbf    1000    464a
0000020    I   F  \0 001 001 001  \0   H  \0   H  \0  \0   �  **  **   �
             4649    0100    0101    4800    4800    0000    bfef    efbd

Это точно такой же код. Я просто переместил .war и запустил его на другой машине. (Разве Java не должна быть написана один раз, работать везде?)

Есть идеи? Проблема "кодирования"?

Код отправляется на ответ так:

   response.contentType = "image/jpeg"; response.outputStream << out;

Вот код, который находит изображение на внутреннем сервере приложений и повторно передает изображение. Я немного сократил код, чтобы убрать обработку ошибок и т. Д., Чтобы было легче читать.

def show = {
    def address = "http://internal.application.server:9899/img?photoid=${params.id}"

    def out = new ByteArrayOutputStream()
    out << new URL(address).openStream()    

    response.contentLength = out.size();

    // XXX If you don't do this hack, "head" requests won't work!
    if (request.method == 'HEAD')
    { render( text : "", contentType : "image/jpeg" ); }
    else {
        response.contentType = "image/jpeg"; response.outputStream << out;
    }
}

Обновление: я попытался установить кодировку символов

response.setCharacterEncoding("ISO-8859-1");

if (request.method == 'HEAD')
{ render( text : "", contentType : "image/jpeg" ); }
        else {
            response.contentType = "image/jpeg;charset=ISO-8859-1";  response.outputStream << out;
 }

но это не имело никакого значения в выводе. На моей рабочей машине двоичные байты в изображении перекодируются / экранируются, как если бы они были в формате UTF-8 (см. Объяснение Майкла ниже). Он отлично работает на моей машине разработки.

Ответы [ 2 ]

2 голосов
/ 05 апреля 2010

Проблема "кодирования"?

Абсолютно. Последовательность "bfef efbd bdbf bfef efbd bdbf" на самом деле представляет собой 4 повторения UTF-8 (с прямым порядком байтов) для кодовой точки U + FFFD REPLACEMENT CHARACTER. Так что в какой-то момент ваши двоичные данные интерпретируются как символьные данные UTF-8, и, конечно, они не являются действительными UTF-8.

Почти наверняка ваш рабочий бокс использует UTF-8 в качестве кодировки по умолчанию для платформы, в то время как блок разработчика использует биективное кодирование ISO-8859.

Но проблема здесь не в использовании кодировки платформы по умолчанию. Проблема в том, что ваши двоичные данные преобразуются в символьные данные и обратно. И это почти наверняка вина вашего кода. Как вы читаете изображения / создаете и заполняете переменную out?

EDIT: Глядя на код, кажется, нет ничего явно неправильного. Но я немного подозрительно отношусь к этим операторам сдвига и преобразованию типа Groovy и преобразованию простоты в отношении перегруженного leftShift() метода OutputStream. Чтобы точно определить проблему, попробуйте просмотреть содержимое ByteArrayOutputStream, а также прочитать первые байты непосредственно с сервера приложений, чтобы увидеть, где именно что-то пойдет не так.

Или, возможно, проблема еще дальше - IIRC, groovy использует sitemesh для обеспечения модульных макетов. Возможно, это виновник, пытающийся проанализировать выходные данные контроллера как HTML. Не уверен, как его выключить, хотя.

1 голос
/ 05 апреля 2010

Я исправил это!

Большое спасибо Майклу Боргвардту, который направил меня в правильном направлении.

Я изменил это:

if (request.method == 'HEAD')
{ render( text : "", contentType : "image/jpeg" ); }
else {
    response.contentType = "image/jpeg"; response.outputStream << out;
}

на это:

if (request.method == 'HEAD')
{ render( text : "", contentType : "image/jpeg" ); }
else {
    response.contentType = "image/jpeg"; response.outputStream << out.toByteArray()
}

обратите внимание на "toByteArray ()") Это предотвратило groovy / grails / java / spring / hibernate / tomcat или что-либо еще, что мешало мне решить перекодировать мои двоичные данные.

...