복붙노트

PHP로 작업하는 Java HttpClient 라이브러리를 사용하여 파일을 업로드하는 방법

PHP

PHP로 작업하는 Java HttpClient 라이브러리를 사용하여 파일을 업로드하는 방법

나는 PHP로 아파치 서버에 파일을 업로드 할 자바 애플리케이션을 작성하고 싶다. Java 코드는 Jakarta HttpClient 라이브러리 버전 4.0 beta2를 사용합니다.

import java.io.File;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.HttpVersion;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.FileEntity;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.params.CoreProtocolPNames;
import org.apache.http.util.EntityUtils;


public class PostFile {
  public static void main(String[] args) throws Exception {
    HttpClient httpclient = new DefaultHttpClient();
    httpclient.getParams().setParameter(CoreProtocolPNames.PROTOCOL_VERSION, HttpVersion.HTTP_1_1);

    HttpPost httppost = new HttpPost("http://localhost:9002/upload.php");
    File file = new File("c:/TRASH/zaba_1.jpg");

    FileEntity reqEntity = new FileEntity(file, "binary/octet-stream");

    httppost.setEntity(reqEntity);
    reqEntity.setContentType("binary/octet-stream");
    System.out.println("executing request " + httppost.getRequestLine());
    HttpResponse response = httpclient.execute(httppost);
    HttpEntity resEntity = response.getEntity();

    System.out.println(response.getStatusLine());
    if (resEntity != null) {
      System.out.println(EntityUtils.toString(resEntity));
    }
    if (resEntity != null) {
      resEntity.consumeContent();
    }

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

PHP 파일 upload.php는 매우 간단합니다 :

<?php
if (is_uploaded_file($_FILES['userfile']['tmp_name'])) {
  echo "File ". $_FILES['userfile']['name'] ." uploaded successfully.\n";
  move_uploaded_file ($_FILES['userfile'] ['tmp_name'], $_FILES['userfile'] ['name']);
} else {
  echo "Possible file upload attack: ";
  echo "filename '". $_FILES['userfile']['tmp_name'] . "'.";
  print_r($_FILES);
}
?>

응답을 읽으면 나는 다음과 같은 결과를 얻는다.

executing request POST http://localhost:9002/upload.php HTTP/1.1
HTTP/1.1 200 OK
Possible file upload attack: filename ''.
Array
(
)

그래서 요청은 성공적이었고 서버와 통신 할 수 있었지만 PHP는 파일을 알아 내지 못했습니다. is_uploaded_file 메서드는 false를 반환하고 $ _FILES 변수는 비어 있습니다. 왜 이런 일이 일어날 지 모르겠다. HTTP 응답 및 요청을 추적했으며 확인되었습니다. 요청은 다음과 같습니다.

POST /upload.php HTTP/1.1
Content-Length: 13091
Content-Type: binary/octet-stream
Host: localhost:9002
Connection: Keep-Alive
User-Agent: Apache-HttpClient/4.0-beta2 (java 1.5)
Expect: 100-Continue

˙Ř˙ŕ..... the rest of the binary file...

응답 :

HTTP/1.1 100 Continue

HTTP/1.1 200 OK
Date: Wed, 01 Jul 2009 06:51:57 GMT
Server: Apache/2.2.8 (Win32) DAV/2 mod_ssl/2.2.8 OpenSSL/0.9.8g mod_autoindex_color PHP/5.2.5 mod_jk/1.2.26
X-Powered-By: PHP/5.2.5
Content-Length: 51
Keep-Alive: timeout=5, max=100
Connection: Keep-Alive
Content-Type: text/html

Possible file upload attack: filename ''.Array
(
)

나는 xampp과 원격 리눅스 서버가있는 로컬 윈도우 XP에서 이것을 테스트했다. 또한 이전 버전의 HttpClient (버전 3.1)를 사용하려고 시도했지만 그 결과는 더 명확하지 않지만 is_uploaded_file은 false를 반환했지만 $ _FILES 배열은 적절한 데이터로 채워졌습니다.

해결법

  1. ==============================

    1.좋아, 내가 사용하는 자바 코드가 잘못됐다, 여기에 바로 자바 클래스가 온다 :

    좋아, 내가 사용하는 자바 코드가 잘못됐다, 여기에 바로 자바 클래스가 온다 :

    import java.io.File;
    import org.apache.http.HttpEntity;
    import org.apache.http.HttpResponse;
    import org.apache.http.HttpVersion;
    import org.apache.http.client.HttpClient;
    import org.apache.http.client.methods.HttpPost;
    import org.apache.http.entity.mime.MultipartEntity;
    import org.apache.http.entity.mime.content.ContentBody;
    import org.apache.http.entity.mime.content.FileBody;
    import org.apache.http.impl.client.DefaultHttpClient;
    import org.apache.http.params.CoreProtocolPNames;
    import org.apache.http.util.EntityUtils;
    
    
    public class PostFile {
      public static void main(String[] args) throws Exception {
        HttpClient httpclient = new DefaultHttpClient();
        httpclient.getParams().setParameter(CoreProtocolPNames.PROTOCOL_VERSION, HttpVersion.HTTP_1_1);
    
        HttpPost httppost = new HttpPost("http://localhost:9001/upload.php");
        File file = new File("c:/TRASH/zaba_1.jpg");
    
        MultipartEntity mpEntity = new MultipartEntity();
        ContentBody cbFile = new FileBody(file, "image/jpeg");
        mpEntity.addPart("userfile", cbFile);
    
    
        httppost.setEntity(mpEntity);
        System.out.println("executing request " + httppost.getRequestLine());
        HttpResponse response = httpclient.execute(httppost);
        HttpEntity resEntity = response.getEntity();
    
        System.out.println(response.getStatusLine());
        if (resEntity != null) {
          System.out.println(EntityUtils.toString(resEntity));
        }
        if (resEntity != null) {
          resEntity.consumeContent();
        }
    
        httpclient.getConnectionManager().shutdown();
      }
    }
    

    MultipartEntity를 사용하여 note합니다.

  2. ==============================

    2.MultipartEntity를 사용하려는 사람들을위한 업데이트 ...

    MultipartEntity를 사용하려는 사람들을위한 업데이트 ...

    org.apache.http.entity.mime.MultipartEntity는 4.3.1에서 더 이상 사용되지 않습니다.

    MultipartEntityBuilder를 사용하여 HttpEntity 객체를 만들 수 있습니다.

    File file = new File();
    
    HttpEntity httpEntity = MultipartEntityBuilder.create()
        .addBinaryBody("file", file, ContentType.create("image/jpeg"), file.getName())
        .build();
    

    Maven 사용자의 경우 클래스는 다음 종속성에서 사용할 수 있습니다 (fervisa의 대답과 거의 동일하지만 이후 버전에서만 사용 가능).

    <dependency>
      <groupId>org.apache.httpcomponents</groupId>
      <artifactId>httpmime</artifactId>
      <version>4.3.1</version>
    </dependency>
    
  3. ==============================

    3.올바른 방법은 멀티 파트 POST 메서드를 사용하는 것입니다. 클라이언트 코드 예는 여기를 참조하십시오.

    올바른 방법은 멀티 파트 POST 메서드를 사용하는 것입니다. 클라이언트 코드 예는 여기를 참조하십시오.

    PHP의 경우 많은 자습서를 사용할 수 있습니다. 이것이 내가 처음으로 발견 한 것입니다. 먼저 html 클라이언트를 사용하여 PHP 코드를 테스트 한 다음 Java 클라이언트를 사용해 보는 것이 좋습니다.

  4. ==============================

    4.나는 같은 문제에 부딪혔다. 그리고 파일 이름이 httpclient 4.x가 PHP 백엔드에서 작동하는 데 필요하다는 것을 알았다. 그것은 httpclient 3.x의 경우가 아닙니다.

    나는 같은 문제에 부딪혔다. 그리고 파일 이름이 httpclient 4.x가 PHP 백엔드에서 작동하는 데 필요하다는 것을 알았다. 그것은 httpclient 3.x의 경우가 아닙니다.

    그래서 내 솔루션 FileBody 생성자에 이름 매개 변수를 추가하는 것입니다. ContentBody cbFile = 새 FileBody (file, "image / jpeg", "FILE_NAME");

    희망이 도움이됩니다.

  5. ==============================

    5.새로운 버전의 예제가 있습니다.

    새로운 버전의 예제가 있습니다.

    원본 코드의 사본은 다음과 같습니다.

    /*
     * ====================================================================
     * Licensed to the Apache Software Foundation (ASF) under one
     * or more contributor license agreements.  See the NOTICE file
     * distributed with this work for additional information
     * regarding copyright ownership.  The ASF licenses this file
     * to you under the Apache License, Version 2.0 (the
     * "License"); you may not use this file except in compliance
     * with the License.  You may obtain a copy of the License at
     *
     *   http://www.apache.org/licenses/LICENSE-2.0
     *
     * Unless required by applicable law or agreed to in writing,
     * software distributed under the License is distributed on an
     * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
     * KIND, either express or implied.  See the License for the
     * specific language governing permissions and limitations
     * under the License.
     * ====================================================================
     *
     * This software consists of voluntary contributions made by many
     * individuals on behalf of the Apache Software Foundation.  For more
     * information on the Apache Software Foundation, please see
     * <http://www.apache.org/>.
     *
     */
    package org.apache.http.examples.entity.mime;
    
    import java.io.File;
    
    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.entity.mime.content.FileBody;
    import org.apache.http.entity.mime.content.StringBody;
    import org.apache.http.impl.client.CloseableHttpClient;
    import org.apache.http.impl.client.HttpClients;
    import org.apache.http.util.EntityUtils;
    
    /**
     * 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();
            }
        }
    
    }
    
  6. ==============================

    6.이름 매개 변수를 추가하기 만하면됩니다.

    이름 매개 변수를 추가하기 만하면됩니다.

    FileBody constructor. ContentBody cbFile = new FileBody(file, "image/jpeg", "FILE_NAME");
    

    희망이 도움이됩니다.

  7. ==============================

    7.나는 파티에 늦었다는 것을 알았지 만,이 문제를 해결하는 올바른 방법은 FileBody 대신 InputStreamBody를 사용하여 멀티 파트 파일을 업로드하는 것입니다.

    나는 파티에 늦었다는 것을 알았지 만,이 문제를 해결하는 올바른 방법은 FileBody 대신 InputStreamBody를 사용하여 멀티 파트 파일을 업로드하는 것입니다.

       try {
            HttpClient httpclient = new DefaultHttpClient();
            HttpPost postRequest = new HttpPost("https://someserver.com/api/path/");
            postRequest.addHeader("Authorization",authHeader);
            //don't set the content type here            
            //postRequest.addHeader("Content-Type","multipart/form-data");
            MultipartEntity reqEntity = new MultipartEntity(HttpMultipartMode.BROWSER_COMPATIBLE);
    
    
            File file = new File(filePath);
            FileInputStream fileInputStream = new FileInputStream(file);
            reqEntity.addPart("parm-name", new InputStreamBody(fileInputStream,"image/jpeg","file_name.jpg"));
    
            postRequest.setEntity(reqEntity);
            HttpResponse response = httpclient.execute(postRequest);
    
            }catch(Exception e) {
                Log.e("URISyntaxException", e.toString());
       }
    
  8. ==============================

    8.로컬 WAMP에서이 파일을 테스트하는 경우 파일 업로드를 위해 임시 폴더를 설정해야 할 수 있습니다. PHP.ini 파일에서 다음과 같이 할 수 있습니다 :

    로컬 WAMP에서이 파일을 테스트하는 경우 파일 업로드를 위해 임시 폴더를 설정해야 할 수 있습니다. PHP.ini 파일에서 다음과 같이 할 수 있습니다 :

    upload_tmp_dir = "c:\mypath\mytempfolder\"
    

    업로드를 허용하려면 폴더에 대한 사용 권한을 부여해야합니다. 부여해야하는 사용 권한은 운영 체제에 따라 다릅니다.

  9. ==============================

    9.허용 된 응답 (org.apache.http.entity.mime.MultipartEntity가 필요함)을 구현하는 데 어려움을 겪고있는 경우 org.apache.httpcomponents 4.2. *를 사용할 수 있습니다. 이 경우 명시 적으로 httpmime 의존성을 설치해야합니다.

    허용 된 응답 (org.apache.http.entity.mime.MultipartEntity가 필요함)을 구현하는 데 어려움을 겪고있는 경우 org.apache.httpcomponents 4.2. *를 사용할 수 있습니다. 이 경우 명시 적으로 httpmime 의존성을 설치해야합니다.

    <dependency>
        <groupId>org.apache.httpcomponents</groupId>
        <artifactId>httpmime</artifactId>
        <version>4.2.5</version>
    </dependency>
    
  10. ==============================

    10.apache http 라이브러리를 사용하여 게시물로 이미지를 보내는 작업 솔루션이 있습니다 (여기서는 경계 추가가 중요합니다. 연결이 없으면 작동하지 않습니다).

    apache http 라이브러리를 사용하여 게시물로 이미지를 보내는 작업 솔루션이 있습니다 (여기서는 경계 추가가 중요합니다. 연결이 없으면 작동하지 않습니다).

                ByteArrayOutputStream baos = new ByteArrayOutputStream();
                bitmap.compress(Bitmap.CompressFormat.PNG, 100, baos);
                byte[] imageBytes = baos.toByteArray();
    
                HttpClient httpclient = new DefaultHttpClient();
                HttpPost httpPost = new HttpPost(StaticData.AMBAJE_SERVER_URL + StaticData.AMBAJE_ADD_AMBAJ_TO_GROUP);
    
                String boundary = "-------------" + System.currentTimeMillis();
    
                httpPost.setHeader("Content-type", "multipart/form-data; boundary="+boundary);
    
                ByteArrayBody bab = new ByteArrayBody(imageBytes, "pic.png");
                StringBody sbOwner = new StringBody(StaticData.loggedUserId, ContentType.TEXT_PLAIN);
                StringBody sbGroup = new StringBody("group", ContentType.TEXT_PLAIN);
    
                HttpEntity entity = MultipartEntityBuilder.create()
                        .setMode(HttpMultipartMode.BROWSER_COMPATIBLE)
                        .setBoundary(boundary)
                        .addPart("group", sbGroup)
                        .addPart("owner", sbOwner)
                        .addPart("image", bab)
                        .build();
    
                httpPost.setEntity(entity);
    
                try {
                    HttpResponse response = httpclient.execute(httpPost);
                    ...then reading response
    
  11. from https://stackoverflow.com/questions/1067655/how-to-upload-a-file-using-java-httpclient-library-working-with-php by cc-by-sa and MIT license