Как отправить символ UTF-8 в виде строки через HTTP - PullRequest
0 голосов
/ 22 января 2020

Я пытаюсь отправить файл по HTTP, используя MultipartEntityBuilder. Мы отправляем «filename» как строковый атрибут в addBinaryBody, как показано ниже. Проблема в том, что имя файла имеет некоторые специальные символы, такие как

"gültig / Kapitel / 00/00 / SOPs / SOP / sop123.pdf"

Но когда это происходит по HTTP это выглядит как

"g? ltig / Kapitel / 00/00 / SOPs / SOP / sop003986.pdf"

Я пробовал URLDecoder и новую строку ( байты, StandardCharsets.UTF_8). Ничего не работает Пожалуйста, предложите несколько ответов.

Требуемый ответ:

Специальные символы должны go как "gültig" вместо "g? Ltig"

MultipartEntityBuilder builder = MultipartEntityBuilder.create();
    builder.addTextBody("index", docbase_name.toLowerCase() + "_content_index");
    builder.addBinaryBody("file", fileContent, ContentType.MULTIPART_FORM_DATA,filename);
    HttpEntity multipart = builder.build();
    HttpPost request = new HttpPost(
            "http://" + utility.getIp()
                + ":" + utility.getPort() + "/fscrawler/_upload");
    request.setEntity(multipart);

1 Ответ

1 голос
/ 22 января 2020

filename следует передать в addBinaryBody, закодированный как заголовок RF C 2047, вы можете использовать MimeUtility из java mail api для выполнения кодирования (см., Например, похожую проблему Как поставить и получить UTF -8 строка из HTTP-заголовка с майкой? ):

builder.addBinaryBody("file", fileContent, ContentType.MULTIPART_FORM_DATA, MimeUtility.encodeText(filename));

setEntity становится:

        request.setEntity(
                MultipartEntityBuilder.create()
                        .addTextBody("index", docbase_name.toLowerCase() + "_content_index")
                        .addBinaryBody("file",
                                fileContent,
                                ContentType.MULTIPART_FORM_DATA,
                                MimeUtility.encodeText(filename))
                        .build());

Полный тестовый пример:

package com.github.vtitov.test;

import com.google.common.base.Charsets;
import com.google.common.io.CharStreams;
import org.apache.http.HttpEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.mime.MultipartEntityBuilder;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import org.glassfish.jersey.logging.LoggingFeature;
import org.glassfish.jersey.media.multipart.FormDataBodyPart;
import org.glassfish.jersey.media.multipart.FormDataMultiPart;
import org.glassfish.jersey.server.ResourceConfig;
import org.glassfish.jersey.test.JerseyTest;
import org.glassfish.jersey.test.TestProperties;
import org.junit.Test;

import javax.mail.internet.MimeUtility;
import javax.ws.rs.Consumes;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.core.Application;

import java.io.IOException;
import java.io.InputStreamReader;
import java.nio.charset.StandardCharsets;
import java.util.LinkedList;
import java.util.List;
import java.util.UUID;
import java.util.logging.Formatter;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.logging.SimpleFormatter;

import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.notNullValue;

public class RestTest extends JerseyTest {
    private final static Logger log = Logger.getLogger(MockHttpResource.class.getName());

    @Path("fscrawler")
    public static class FscrawlerResource {
        @POST
        @Consumes("multipart/form-data")
        @Path("_upload")
        public String postToString(final FormDataMultiPart multiPart) throws Exception {
            List<String> fileNames = new LinkedList<>();
            try {
                for(FormDataBodyPart f:multiPart.getFields().get("file")) {
                    fileNames.add(MimeUtility.decodeText(f.getContentDisposition().getFileName()));
                }
            } catch (Exception e) {
                log.log(Level.SEVERE, "server error: ", e);
                throw e;
            }
            return String.join(",", fileNames);
        }
    }

    @Override
    protected Application configure() {
        forceSet(TestProperties.CONTAINER_PORT, "0");
        set(TestProperties.RECORD_LOG_LEVEL, Level.INFO.intValue());
        set(TestProperties.RECORD_LOG_LEVEL, Level.FINE.intValue());
        return new ResourceConfig(FscrawlerResource.class)
                .register(LoggingFeature.class)
                .register(org.glassfish.jersey.media.multipart.MultiPartFeature.class)
                ;
    }

    @Test
    public void multipart() throws IOException {
        String baseUri = target().getUri().toString();
        String docbase_name = UUID.randomUUID().toString();
        byte[] fileContent = UUID.randomUUID().toString().getBytes(StandardCharsets.UTF_8);
        String  filename = "gültig/file.txt";

        HttpPost request = new HttpPost(baseUri + "fscrawler/_upload");
        request.setEntity(
                MultipartEntityBuilder.create()
                        .addTextBody("index", docbase_name.toLowerCase() + "_content_index")
                        .addBinaryBody("file",
                                fileContent,
                                ContentType.MULTIPART_FORM_DATA,
                                MimeUtility.encodeText(filename))
                        .build());

        log.info("executing request " + request.getRequestLine());
        try(CloseableHttpClient httpclient = HttpClients.createDefault();
            CloseableHttpResponse response = httpclient.execute(request)
        ) {
            log.info(String.format("response: %s", response.toString()));
            HttpEntity resEntity = response.getEntity();
            assertThat(resEntity, notNullValue());
            if (resEntity != null) {
                log.info("Response content length: " + resEntity.getContentLength());
                String resContent = CharStreams.toString(new InputStreamReader(resEntity.getContent(), Charsets.UTF_8));
                log.info(String.format("response content: %s", resContent));
                assertThat("filename matches", filename, equalTo(resContent));
            }
            EntityUtils.consume(resEntity);
        } catch (IOException e) {
            dumpServerLogRecords();
            throw e;
        }
        dumpServerLogRecords();
    }

    void dumpServerLogRecords() {
        log.info(String.format("total server log records: %s", getLoggedRecords().size()));
        Formatter sf = new SimpleFormatter();
        getLoggedRecords().forEach(r -> {
            log.info(String.format("server log record\n%s", sf.format(r)));
        });

    }
}

Вы можно включить ведение журнала для просмотра запросов, ответов и обработки:

mvn test \
  -Dorg.apache.commons.logging.Log=org.apache.commons.logging.impl.SimpleLog \
  -Dorg.apache.commons.logging.simplelog.showdatetime=true \
  -Dorg.apache.commons.logging.simplelog.log.org.apache.http=DEBUG \
  -Dorg.apache.commons.logging.simplelog.log.org.apache.http.wire=DEBUG
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...