Java를 사용하여 멀티 파트 / 양식 데이터 POST 요청을하려면 어떻게해야합니까?


96

Apache Commons HttpClient 3.x 버전에서는 multipart / form-data POST 요청을 만들 수있었습니다 ( 2004 년의 예 ). 불행히도 이것은 HttpClient 버전 4.0 에서는 더 이상 가능하지 않습니다 .

핵심 활동 "HTTP"의 경우 multipart는 다소 범위를 벗어납니다. 우리는 범위 내에있는 다른 프로젝트에서 유지 관리하는 멀티 파트 코드를 사용하고 싶지만 어떤 것도 알지 못합니다. 우리는 몇 년 전에 멀티 파트 코드를 commons-codec으로 옮기려고했지만 거기서 벗어나지 않았습니다. Oleg는 최근에 multipart 구문 분석 코드가 있고 우리의 multipart 형식화 코드에 관심이있을 수있는 또 다른 프로젝트를 언급했습니다. 나는 그것에 대한 현재 상태를 모른다. ( http://www.nabble.com/multipart-form-data-in-4.0-td14224819.html )

multipart / form-data POST 요청을 할 수있는 HTTP 클라이언트를 작성할 수있는 Java 라이브러리를 아는 사람이 있습니까?

배경 : Zoho WriterRemote API 를 사용하고 싶습니다 .


답변:


152

HttpClient 4.x를 사용하여 다중 파일 게시를 만듭니다.

업데이트 : HttpClient 4.3 부터 일부 클래스가 더 이상 사용되지 않습니다. 다음은 새 API가있는 코드입니다.

CloseableHttpClient httpClient = HttpClients.createDefault();
HttpPost uploadFile = new HttpPost("...");
MultipartEntityBuilder builder = MultipartEntityBuilder.create();
builder.addTextBody("field1", "yes", ContentType.TEXT_PLAIN);

// This attaches the file to the POST:
File f = new File("[/path/to/upload]");
builder.addBinaryBody(
    "file",
    new FileInputStream(f),
    ContentType.APPLICATION_OCTET_STREAM,
    f.getName()
);

HttpEntity multipart = builder.build();
uploadFile.setEntity(multipart);
CloseableHttpResponse response = httpClient.execute(uploadFile);
HttpEntity responseEntity = response.getEntity();

다음은 더 이상 사용되지 않는 HttpClient 4.0 API 가있는 원래 코드 스 니펫입니다 .

HttpClient httpclient = new DefaultHttpClient();
HttpPost httppost = new HttpPost(url);

FileBody bin = new FileBody(new File(fileName));
StringBody comment = new StringBody("Filename: " + fileName);

MultipartEntity reqEntity = new MultipartEntity();
reqEntity.addPart("bin", bin);
reqEntity.addPart("comment", comment);
httppost.setEntity(reqEntity);

HttpResponse response = httpclient.execute(httppost);
HttpEntity resEntity = response.getEntity();

63
아, 멀티 파트는 org.apache.httpcomponents-httpmime-4.0으로 옮겨졌습니다! 어딘가에 언급 될 수 있습니다 : /

작은 파일에서는 잘 작동하지만 큰 파일에서는 작동하지 않는 업데이트 된 코드를 시도했습니다. 당신이 좀 도와 줄래 질문
AabinGunz

안녕하세요 ZZ, 저는 위의 코드를 변경했지만 이제 새로운 문제에 직면 해 있습니다. REST 엔드 포인트가 요청을 수락하지 않습니다. 다음 매개 변수가 필요합니다. ~ @ PathVariable final String id, @RequestParam ( "image") final MultipartFile image, @RequestParam ( "l") final String l, @RequestParam ( "lo") final String lo, @RequestParam ( " bac ") final String bac, @RequestParam ("cac ") final String cac, @RequestParam ("m ") final String m ... 이전에는 요청이 수락되었습니다. 하지만 지금은 500 오류가 발생합니다. 왜 이런 일이 일어날 지 아이디어가 있습니까?
Logan

나는 코드 예제가 더 이상 수평 스크롤하지 않도록 대답을 편집했습니다 .--- 스크롤로 인해 내 작업에서 사용하려고 할 때 중요한 최종 매개 변수를 놓쳤습니다.
G. Sylvie Davies

다음은 업데이트 된 답변 <dependency> <groupId> org.apache.httpcomponents </ groupId> <artifactId> httpclient </ artifactId> <version> 4.3.6 </ version> </ dependency> <!-에 대한 Maven 종속성입니다. mvnrepository.com/artifact/org.apache.httpcomponents/httpmime- > <dependency> <groupId> org.apache.httpcomponents </ groupId> <artifactId> httpmime </ artifactId> <version> 4.3.6 </ version> < / dependency>
Wazime

39

이것이 내가 가진 Maven 의존성입니다.

자바 코드 :

HttpClient httpclient = new DefaultHttpClient();
HttpPost httpPost = new HttpPost(url);

FileBody uploadFilePart = new FileBody(uploadFile);
MultipartEntity reqEntity = new MultipartEntity();
reqEntity.addPart("upload-file", uploadFilePart);
httpPost.setEntity(reqEntity);

HttpResponse response = httpclient.execute(httpPost);

pom.xml의 Maven 종속성 :

<dependency>
  <groupId>org.apache.httpcomponents</groupId>
  <artifactId>httpclient</artifactId>
  <version>4.0.1</version>
  <scope>compile</scope>
</dependency>
<dependency>
  <groupId>org.apache.httpcomponents</groupId>
  <artifactId>httpmime</artifactId>
  <version>4.0.1</version>
  <scope>compile</scope>
</dependency>

1
당신은을 위해, 적어도 4.2,뿐만 아니라 httpcore 필요합니다 HttpEntity클래스
alalonde

19

JAR의 크기가 중요한 경우 (예 : 애플릿의 경우), HttpClient 대신 java.net.HttpURLConnection과 함께 httpmime를 직접 사용할 수도 있습니다.

httpclient-4.2.4:      423KB
httpmime-4.2.4:         26KB
httpcore-4.2.4:        222KB
commons-codec-1.6:     228KB
commons-logging-1.1.1:  60KB
Sum:                   959KB

httpmime-4.2.4:         26KB
httpcore-4.2.4:        222KB
Sum:                   248KB

암호:

HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setDoOutput(true);
connection.setRequestMethod("POST");

FileBody fileBody = new FileBody(new File(fileName));
MultipartEntity multipartEntity = new MultipartEntity(HttpMultipartMode.STRICT);
multipartEntity.addPart("file", fileBody);

connection.setRequestProperty("Content-Type", multipartEntity.getContentType().getValue());
OutputStream out = connection.getOutputStream();
try {
    multipartEntity.writeTo(out);
} finally {
    out.close();
}
int status = connection.getResponseCode();
...

pom.xml의 종속성 :

<dependency>
    <groupId>org.apache.httpcomponents</groupId>
    <artifactId>httpmime</artifactId>
    <version>4.2.4</version>
</dependency>

FileBody는 어디에서 왔습니까? apace.httpcomponents를 사용하지 않는 (쉬운) 방법이 있습니까?
Jr.

6

이 코드를 사용하여 post in multipart를 사용하여 이미지 또는 기타 파일을 서버에 업로드합니다.

import java.io.File;
import java.io.IOException;
import java.io.UnsupportedEncodingException;

import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.ResponseHandler;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.mime.MultipartEntity;
import org.apache.http.entity.mime.content.FileBody;
import org.apache.http.entity.mime.content.StringBody;
import org.apache.http.impl.client.BasicResponseHandler;
import org.apache.http.impl.client.DefaultHttpClient;

public class SimplePostRequestTest {

    public static void main(String[] args) throws UnsupportedEncodingException, IOException {
        HttpClient httpclient = new DefaultHttpClient();
        HttpPost httppost = new HttpPost("http://192.168.0.102/uploadtest/upload_photo");

        try {
            FileBody bin = new FileBody(new File("/home/ubuntu/cd.png"));
            StringBody id = new StringBody("3");
            MultipartEntity reqEntity = new MultipartEntity();
            reqEntity.addPart("upload_image", bin);
            reqEntity.addPart("id", id);
            reqEntity.addPart("image_title", new StringBody("CoolPic"));

            httppost.setEntity(reqEntity);
            System.out.println("Requesting : " + httppost.getRequestLine());
            ResponseHandler<String> responseHandler = new BasicResponseHandler();
            String responseBody = httpclient.execute(httppost, responseHandler);
            System.out.println("responseBody : " + responseBody);

        } catch (ClientProtocolException e) {

        } finally {
            httpclient.getConnectionManager().shutdown();
        }
    }

}

업로드하려면 아래 파일이 필요합니다.

라이브러리는 다음 httpclient-4.1.2.jar, httpcore-4.1.2.jar, httpmime-4.1.2.jar, httpclient-cache-4.1.2.jar, commons-codec.jarcommons-logging-1.1.1.jar클래스 경로에있을 수 있습니다.


4

HTTP 클라이언트를 기반으로 하는 REST Assured 를 사용할 수도 있습니다 . 매우 간단합니다.

given().multiPart(new File("/somedir/file.bin")).when().post("/fileUpload");

"파일"이라는 제어 이름을 가정합니다. 그런 다음 다른 컨트롤 이름이 있다면 당신은 그것을 지정해야합니다 multiPart("controlName", new File("/somedir/file.bin"))참조 github.com/rest-assured/rest-assured/wiki/...
asmaier

REST Assured는 훌륭한 API를 가지고 있으며 많은 기능을 지원합니다. 그것으로 일하는 것은 즐거움입니다. 그러나 공정하게 말하면 일부 워밍업 절차로 인해 첫 번째 호출에서 성능이 저하 될 수 있음을 언급 할 가치가 있습니다. 인터넷에서 더 많은 정보를 찾을 수 있습니다. 즉 sqa.stackexchange.com/questions/39532/…
user1053510

REST Assured는 훌륭한 라이브러리이지만 Web API 테스트를 위해 설계되었으며 물론 동일한 기본 라이브러리를 사용하더라도 프로덕션 코드에서 HTTP 호출을 수행하는 데 적합한 도구라고 생각하지 않습니다.
Ranil Wijeyratne

3

여기에 라이브러리가 필요하지 않은 솔루션이 있습니다.

이 루틴은 디렉토리의 모든 파일 d:/data/mpf10urlToConnect


String boundary = Long.toHexString(System.currentTimeMillis());
URLConnection connection = new URL(urlToConnect).openConnection();
connection.setDoOutput(true);
connection.setRequestProperty("Content-Type", "multipart/form-data; boundary=" + boundary);
PrintWriter writer = null;
try {
    writer = new PrintWriter(new OutputStreamWriter(connection.getOutputStream(), "UTF-8"));
    File dir = new File("d:/data/mpf10");
    for (File file : dir.listFiles()) {
        if (file.isDirectory()) {
            continue;
        }
        writer.println("--" + boundary);
        writer.println("Content-Disposition: form-data; name=\"" + file.getName() + "\"; filename=\"" + file.getName() + "\"");
        writer.println("Content-Type: text/plain; charset=UTF-8");
        writer.println();
        BufferedReader reader = null;
        try {
            reader = new BufferedReader(new InputStreamReader(new FileInputStream(file), "UTF-8"));
            for (String line; (line = reader.readLine()) != null;) {
                writer.println(line);
            }
        } finally {
            if (reader != null) {
                reader.close();
            }
        }
    }
    writer.println("--" + boundary + "--");
} finally {
    if (writer != null) writer.close();
}
// Connection is lazily executed whenever you request any status.
int responseCode = ((HttpURLConnection) connection).getResponseCode();
// Handle response

2

httpcomponents-client-4.0.1나를 위해 일했습니다. 그러나 외부 jar apache-mime4j-0.6.jar ( org.apache.james.mime4j ) 를 추가해야했습니다 reqEntity.addPart("bin", bin);. 그렇지 않으면 컴파일되지 않습니다. 이제 매력처럼 작동합니다.


2

Apache의 빠른 시작 가이드 에서이 샘플 을 찾았습니다 . 버전 4.5 용입니다.

/**
 * Example how to use multipart/form encoded POST request.
 */
public class ClientMultipartFormPost {

    public static void main(String[] args) throws Exception {
        if (args.length != 1)  {
            System.out.println("File path not given");
            System.exit(1);
        }
        CloseableHttpClient httpclient = HttpClients.createDefault();
        try {
            HttpPost httppost = new HttpPost("http://localhost:8080" +
                    "/servlets-examples/servlet/RequestInfoExample");

            FileBody bin = new FileBody(new File(args[0]));
            StringBody comment = new StringBody("A binary file of some kind", ContentType.TEXT_PLAIN);

            HttpEntity reqEntity = MultipartEntityBuilder.create()
                    .addPart("bin", bin)
                    .addPart("comment", comment)
                    .build();


            httppost.setEntity(reqEntity);

            System.out.println("executing request " + httppost.getRequestLine());
            CloseableHttpResponse response = httpclient.execute(httppost);
            try {
                System.out.println("----------------------------------------");
                System.out.println(response.getStatusLine());
                HttpEntity resEntity = response.getEntity();
                if (resEntity != null) {
                    System.out.println("Response content length: " + resEntity.getContentLength());
                }
                EntityUtils.consume(resEntity);
            } finally {
                response.close();
            }
        } finally {
            httpclient.close();
        }
    }
}

0

우리는 jdk 외부의 외부 종속성이나 라이브러리를 사용하지 않고 다중 파트 양식 제출의 순수한 Java 구현을 가지고 있습니다. https://github.com/atulsm/https-multipart-purejava/blob/master/src/main/java/com/atul/MultipartPure.java를 참조 하십시오.

private static String body = "{\"key1\":\"val1\", \"key2\":\"val2\"}";
private static String subdata1 = "@@ -2,3 +2,4 @@\r\n";
private static String subdata2 = "<data>subdata2</data>";

public static void main(String[] args) throws Exception{        
    String url = "https://" + ip + ":" + port + "/dataupload";
    String token = "Basic "+ Base64.getEncoder().encodeToString((userName+":"+password).getBytes());

    MultipartBuilder multipart = new MultipartBuilder(url,token);       
    multipart.addFormField("entity", "main", "application/json",body);
    multipart.addFormField("attachment", "subdata1", "application/octet-stream",subdata1);
    multipart.addFormField("attachment", "subdata2", "application/octet-stream",subdata2);        
    List<String> response = multipart.finish();         
    for (String line : response) {
        System.out.println(line);
    }
}

0

내 코드는 multipartFile을 서버에 게시합니다.

  public static HttpResponse doPost(
    String host,
    String path,
    String method,
    MultipartFile multipartFile
  ) throws IOException
  {

    HttpClient httpClient = wrapClient(host);
    HttpPost httpPost = new HttpPost(buildUrl(host, path));

    if (multipartFile != null) {

      HttpEntity httpEntity;

      ContentBody contentBody;
      contentBody = new ByteArrayBody(multipartFile.getBytes(), multipartFile.getOriginalFilename());
      httpEntity = MultipartEntityBuilder.create()
                                         .addPart("nameOfMultipartFile", contentBody)
                                         .build();

      httpPost.setEntity(httpEntity);

    }
    return httpClient.execute(httpPost);
  }
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.