HttpClient 시작 (2) 양식 제출 및 파일 업로드

8171 단어
지난 글에서 HttpClient를 통해 간단한 get 요청을 실현하고 서버가 되돌아오는 자원을 처리했습니다. 많은 장면에서 우리는 서버에 우리의 정보를 업로드해야 합니다.
다음 분석 사용 버전은 httpclient-4.5.3입니다.jar httpcore-4.4.6.jar httpmime-4.5.3.jar jdk1.8.0_131 모든 예시 코드는 실행 테스트를 거쳤다

양식 제출


제3자 인터페이스나 아날로그 폼을 호출하여 제출할 때post 요청에 자주 사용됩니다. get 요청과 달리post 요청의 매개 변수는 URL을 통해 전달되는 것이 아니라 요청 메시지의 본문에 봉인됩니다.HttpClient는 이러한 장면을 처리하기 위해 UrlEncodedFormEntity 클래스를 제공합니다.UrlEncodedFormEntity 인스턴스를 생성할 때 인코딩을 UTF-8로 지정해야 합니다. 그렇지 않으면 중국어가 서버에 도착하면 인코딩이 엉망이 됩니다.
CloseableHttpClient httpclient = null;
CloseableHttpResponse response = null;
try {
    httpclient = HttpClients.createDefault();
    HttpPost post = new HttpPost("http://localhost:8080/Crayfish/HttpClientServer");
    HttpEntity formEntity = getFormEntity();
    post.setEntity(formEntity);
    HttpEntity entity = response.getEntity();
    System.out.println(EntityUtils.toString(entity, "UTF-8"));
} catch (Exception e) {
    e.printStackTrace();
} finally {
    CommonUtils.closeResponse(response);
    CommonUtils.closeHttpClient(httpclient);
}
public HttpEntity getFormEntity() throws UnsupportedEncodingException {
    List formParams = new ArrayList<>();
    formParams.add(new BasicNameValuePair("name", " "));
    formParams.add(new BasicNameValuePair("password", "helloWord!"));
    return new UrlEncodedFormEntity(formParams, "UTF-8");
}

아날로그 서버


요청 효과 테스트를 편리하게 하기 위해 Tomcat+servlet을 기반으로 로컬 서버를 구축하고 수신된 요청 파라미터를 컨트롤러에 직접 출력합니다. 서버 관련 코드는 다음과 같습니다.
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    Map paramMap = request.getParameterMap();
    for (Entry paramEntry : paramMap.entrySet()) {
        String val = paramEntry.getValue()[0];
        String info = String.format("key:%s, val:%s.", paramEntry.getKey(), val);
        System.out.println(info);
    }
    response.getWriter().append("Success!");
}

서버 출력
key:name, val: .
key:password, val:helloWord!.

파일 업로드


양식이 제출될 때 매개 변수는 UrlEncodedForm Entity 클래스에 봉인됩니다.비슷하게 파일이 업로드될 때 파일 정보는 Multipart Form Entity 클래스에 봉인되고 이 두 클래스는 모두 Http Entity 인터페이스를 실현했다.파일 업로드를 편리하게 하기 위해 HttpClients는 Multipart Entity Builder라는 도구 클래스를 제공하여 Multipart Form Entity를 생성합니다. Multipart Entity Builder는 파일 정보를 추가하는 세 가지 방식을 지원합니다. 그것이 바로 File 파일,byte 그룹, Input Stream 파일 흐름입니다.
CloseableHttpClient httpclient = null;
CloseableHttpResponse response = null;
try {
    httpclient = HttpClients.createDefault();
    HttpPost post = new HttpPost("http://localhost:8080/Crayfish/FileUpload");
    HttpEntity dataEntity = getMultiFileEntity();//File 
//  HttpEntity dataEntity = getMultiDefaultFileEntity();//File ( )
//  HttpEntity dataEntity = getMultiArrayEntity();//byte 
//  HttpEntity dataEntity = getMultiDefaultArrayEntity();//byte ( )
//  HttpEntity dataEntity = getMultiStreamEntity();// 
//  HttpEntity dataEntity = getMultiDefaultStreamEntity();// ( )
    post.setEntity(dataEntity);
    response = httpclient.execute(post);
} catch (Exception e) {
    e.printStackTrace();
} finally {
    CommonUtils.closeResponse(response);
    CommonUtils.closeHttpClient(httpclient);
}
/**
 * File 
*/
public HttpEntity getMultiFileEntity() {
    MultipartEntityBuilder builder = MultipartEntityBuilder.create();
    File file = new File("F:/PIC/house.jpeg");;
    builder.addBinaryBody("file", file, ContentType.DEFAULT_BINARY, "photo.jpg");
    return builder.build();
}

/**
 * File ( )
*/
public HttpEntity getMultiDefaultFileEntity() {
    MultipartEntityBuilder builder = MultipartEntityBuilder.create();
    File file = new File("F:/PIC/house.jpeg");
    builder.addBinaryBody("file", file);
    return builder.build();
}

/**
 * byte 
*/
public HttpEntity getMultiArrayEntity() {
    MultipartEntityBuilder builder = MultipartEntityBuilder.create();
    byte[] byteArr = getFileArr();
    builder.addBinaryBody("file", byteArr, ContentType.DEFAULT_BINARY, "photoArr.jpg");
    return builder.build();
}

/**
 * byte ( )
*/
public HttpEntity getMultiDefaultArrayEntity() {
    MultipartEntityBuilder builder = MultipartEntityBuilder.create();
    byte[] byteArr = getFileArr();
    builder.addBinaryBody("file", byteArr);
    return builder.build();
}
    
public byte[] getFileArr() {
    try {
        File file = new File("F:/PIC/house.jpeg");
        FileInputStream fis = new FileInputStream(file);
        ByteArrayOutputStream bos = new ByteArrayOutputStream(1000);  
        byte[] b = new byte[1000];  
        int n;  
        while ((n = fis.read(b)) != -1) {  
            bos.write(b, 0, n);  
        }  
        fis.close();  
        bos.close();  
        return bos.toByteArray(); 
    } catch (Exception e) {
        e.printStackTrace();
        return new byte[0];
    }
}

/**
 *  
*/
 public HttpEntity getMultiStreamEntity() throws FileNotFoundException {
    MultipartEntityBuilder builder = MultipartEntityBuilder.create();
    File file = new File("F:/PIC/house.jpeg");
    InputStream stream = new FileInputStream(file);
    builder.addBinaryBody("file", stream, ContentType.DEFAULT_BINARY, "photoStream.jpg");
    return builder.build();
}

/**
 *  ( )
*/
public HttpEntity getMultiDefaultStreamEntity() throws FileNotFoundException {
    MultipartEntityBuilder builder = MultipartEntityBuilder.create();
    File file = new File("F:/PIC/house.jpeg");
    InputStream stream = new FileInputStream(file);
    builder.addBinaryBody("file", stream);
    return builder.build();
}

파일 형식 업로드
getMultiFileEntity에서 MultipartEntityBuilder의addBinaryBody 방법을 호출했습니다. 첫 번째 매개 변수인'file'은 필드 이름을 대표합니다. , 두 번째 매개 변수는 읽는 파일 클래스, 세 번째 매개 변수인 ContentType입니다.DEFAULT_BINARY는 http 요청을 보낼 때content-type을 응용 프로그램/octet-stream으로 지정하고 네 번째 매개 변수는 파일 이름을 대표합니다.기본 getMultiDefaultFile Entity를 사용할 수도 있습니다. 원본 코드를 보면 content-type이 기본적으로 ContentType입니다.DEFAULT_BINARY, 파일 이름은 파일 원래 이름을 가져옵니다.
public MultipartEntityBuilder addBinaryBody(final String name, final File file) {
        return addBinaryBody(name, file, ContentType.DEFAULT_BINARY, file != null ? file.getName() : null);
}

byte 배열 형식 업로드
getMultiArray Entity에서addBinary Body를 호출할 때, 전송된byte 수조이며, 다른 매개 변수는 첫 번째 방식과 같습니다.byte 배열 방식 업로드는 기본 방식을 제공합니다. (getMultiDefault Array Entity 참조) 기본 방식을 사용하지만, 서버에 업로드하면 파일 이름이null이고 접두사가 없으면 파일의 정상적인 표시에 영향을 줍니다.
파일 흐름 형식 업로드
getMulti Stream Entity에서addBinary Body를 호출할 때 입력 Stream이 전송됩니다. 다른 매개 변수는 첫 번째 방식과 같습니다.파일 흐름 방식을 업로드하고 기본 방식도 제공합니다. (getMultiDefault Stream Entity 참조) 그러나 기본 방식을 사용하면 서버에 업로드하면 파일 이름이null이고 접두사가 없으면 파일의 정상적인 표시에 영향을 줍니다.

서버 수신 코드

protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    try {
        DiskFileItemFactory factory = new DiskFileItemFactory();
        ServletFileUpload fileUpload = new ServletFileUpload(factory);
        List formItems = fileUpload.parseRequest(request);
        for (FileItem item : formItems) {
            String filename = item.getName();
            File newFile = new File("F:/eclipseOutput/PIC/"+filename);
            item.write(newFile);
        }
    } catch (Exception e) {
        e.printStackTrace();
    }   
}

부록 CommonUtils
public void closeResponse(CloseableHttpResponse response) {
    try {
        if (response != null) {
            response.close();
        }
    } catch (Exception e) {
        e.printStackTrace();
    }
}

public void closeHttpClient(CloseableHttpClient httpclient) {
    try {
        if (httpclient != null) {
            httpclient.close();
        }
    } catch (Exception e) {
        e.printStackTrace();
    }
}

좋은 웹페이지 즐겨찾기