代码之家  ›  专栏  ›  技术社区  ›  Piotr Kochański

如何使用Java HttpClient库和PHP一起上传文件

  •  51
  • Piotr Kochański  · 技术社区  · 16 年前

    我想编写一个Java应用程序,用PHP将文件上传到Apache服务器。Java代码使用雅加达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
    (
    )
    

    is_uploaded_file 返回 false $_FILES
    请求是:

    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
    (
    )
    

    是上传的吗 返回 错误的 然而 $\u文件

    10 回复  |  直到 7 年前
        1
  •  66
  •   Brian Agnew    16 年前

    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。

        2
  •  29
  •   Brent Robinson    12 年前

    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
  •   kgiannakakis    16 年前

    正确的方法是使用多部分POST方法。看见 here 例如,客户端的代码。

    对于PHP,有许多可用的教程。这是 first 我找到了。我建议您首先使用html客户机测试PHP代码,然后尝试java客户机。

        4
  •  3
  •   gaojun1000    12 年前

    我遇到了同样的问题,并发现httpclient 4.x使用PHP后端时需要文件名。httpclient 3.x并非如此。

    ContentBody cbFile=新文件体(文件,“图像/jpeg”,“文件名”);

    希望能有帮助。

        5
  •  2
  •   Junaid    10 年前

    A newer version example is here.

    以下是原始代码的副本:

    /*
     * ====================================================================
     * 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
  •  1
  •   Krystian    11 年前

    我的工作解决方案是使用apache http库通过post发送图像(这里非常重要的一点是,在我的连接中,如果没有它,它将无法工作):

                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
    
        7
  •  1
  •   user4286889 user4286889    11 年前

    啊,您只需要在

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

        8
  •  1
  •   Dev    9 年前

    我知道我来晚了,但下面是正确的处理方法,关键是使用 InputStreamBody 代替 FileBody 上传多部分文件。

       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());
       }
    
        9
  •  0
  •   Fenton    16 年前

    如果要在本地WAMP上测试此功能,则可能需要设置临时文件夹以上载文件。您可以在PHP.ini文件中执行此操作:

    upload_tmp_dir = "c:\mypath\mytempfolder\"
    

    您需要授予文件夹的权限才能进行上载-您需要授予的权限因您的操作系统而异。

        10
  •  0
  •   fervisa    12 年前

    对于那些难以实现可接受答案(需要org.apache.http.entity.mime.MultipartEntity)的人,您可以使用org.apache.httpcomponents 4.2* 在这种情况下,你必须 显式安装 httpime 依赖性,在我的例子中:

    <dependency>
        <groupId>org.apache.httpcomponents</groupId>
        <artifactId>httpmime</artifactId>
        <version>4.2.5</version>
    </dependency>
    
    推荐文章