Spring RestTemplate: получение 403 запрещено для multipart / form-data, но работа с curl - PullRequest
2 голосов
/ 05 мая 2020

Я использую шаблон spring rest для запроса POST form-data из 1 файла и 1 строкового параметра, вот код:

    HttpHeaders headers = new HttpHeaders();
    headers.set("Authorization", "Bearer ...");
    httpHeaders.setContentType(MediaType.MULTIPART_FORM_DATA);
    File file=new File("src\main\resources\test.json");
    BufferedInputStream in = new BufferedInputStream(new FileInputStream(file));
    byte[] fileBytes = toByteArray(in);

    MultiValueMap<String, String> fileMap = new LinkedMultiValueMap<>();
    ContentDisposition contentDisposition = ContentDisposition
            .builder("form-data")
            .name("file")
            .filename("test.json")
            .build();
    fileMap.add(HttpHeaders.CONTENT_DISPOSITION, contentDisposition.toString());
    fileMap.add(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE);
    org.springframework.http.HttpEntity<byte[]> fileEntity =
            new org.springframework.http.HttpEntity<>(fileBytes, fileMap);

    MultiValueMap< String, Object > body = new LinkedMultiValueMap<>();
    body.add("stringFormInput", "xyz");
    body.add("file", fileEntity);
    org.springframework.http.HttpEntity< MultiValueMap< String, Object > > entity =
            new org.springframework.http.HttpEntity<>(body, httpHeaders);

    ResponseEntity< JsonNode > responseEntity =
            restTemplate.postForEntity("https://uploadFile", entity, JsonNode.class);

Но я получаю 403 FORBIDDEN ответ

Однако, если я использую команду curl ниже, она успешно выполняется

curl --location --request POST 'https://uploadFile' \
--header 'Content-Type: multipart/form-data' \
--header 'Authorization: Bearer ...' \
--form 'file=@/D:/resources/test.json' \
--form 'stringFormInput=xyz' \

Я также пробовал с httpClient, тем не менее, это 403 без сообщения о какой-либо причине

HttpPost post = new HttpPost("https://uploadFile");
post.setHeader(HttpHeaders.CONTENT_TYPE, MediaType.MULTIPART_FORM_DATA_VALUE);
post.setHeader(HttpHeaders.AUTHORIZATION, "Bearer ...");

File file=new File("src\main\resources\test.json");
MultipartEntityBuilder builder = MultipartEntityBuilder.create();
builder.setMode(HttpMultipartMode.BROWSER_COMPATIBLE);
builder.addBinaryBody("file", file, ContentType.DEFAULT_BINARY, "test.json");
builder.addTextBody("stringFormInput", "xyz", ContentType.DEFAULT_BINARY);
HttpEntity entity = builder.build();

post.setEntity(entity);
HttpClient httpClient = HttpClientBuilder.create().build();
HttpResponse response = httpClient.execute(post);

РЕДАКТИРОВАТЬ

На данный момент я сделал обходной путь, выполнив curl из JAVA

    File file=new File("src\main\resources\test.json");
    String[] command = {"curl", "--location",
            "--request", "POST", "https://uploadFile",
            "--header", "Content-Type: multipart/form-data",
            "--header", "Authorization: Bearer ...",
            "-F", "file=" + "@"+file.getPath(),
            "--form", "stringFormInput=xyz"};

    ProcessBuilder builder = new ProcessBuilder(command);
    builder.redirectErrorStream(true);

    String curlResult = "";
    String line = "";

    try {
        Process process = builder.start();
        BufferedReader r = new BufferedReader(new InputStreamReader(process.getInputStream()));
        while (true) {
            line = r.readLine();
            if (line == null) {
                break;
            }
            curlResult = curlResult + line;
        }
    } catch (Exception e) {
        e.printStackTrace();
    }

1 Ответ

0 голосов
/ 28 августа 2020

Итак, я столкнулся с аналогичной проблемой: cURL выполнялся правильно, но код Spring выдавал 403. Проблема заключается в цели, которая получает этот запрос. Для некоторых веб-серверов, таких как Nginx, по умолчанию требуются обязательные заголовки, такие как «User-Agent», которые можно отключить.

По умолчанию Spring не передает никаких дополнительных заголовков. Попробуйте добавить «User-Agent», если цель использует Ngnix, или найдите, какой веб-сервер они используют.

Поделитесь моим кодом для справки.

  1. Этот код дал 403

    HttpHeaders httpHeaders = new HttpHeaders (); httpHeaders.setContentType (MediaType.MULTIPART_FORM_DATA);

  2. этот код работал нормально.

    HttpHeaders httpHeaders = new HttpHeaders (); httpHeaders.setContentType (MediaType.MULTIPART_FORM_DATA); httpHeaders.add («Пользователь-агент», «PostmanRuntime / 7.26.3»);

...