首页 > 学院 > 开发设计 > 正文

使用HttpClient上传文件

2019-11-06 06:33:02
字体:
来源:转载
供稿:网友

1 HTTP

    HTTP 协议可能是现在 Internet 上使用得最多、最重要的协议了,越来越多的 java 应用程序需要直接通过 HTTP 协议来访问网络资源。

    虽然在 JDK 的 java.net 包中已经提供了访问 HTTP 协议的基本功能,但是对于大部分应用程序来说,JDK 库本身提供的功能还不够丰富和灵活。HttpClient 用来提供高效的、最新的、功能丰富的支持 HTTP 协议的客户端编程工具包,并且它支持 HTTP 协议最新的版本和建议。

    一般的情况下我们都是使用Chrome或者其他浏览器来访问一个WEB服务器,用来浏览页面查看信息或者提交一些数据、文件上传下载等等。所访问的这些页面有的仅仅是一些普通的页面,有的需要用户登录后方可使用,或者需要认证以及是一些通过加密方式传输,例如HTTPS。目前我们使用的浏览器处理这些情况都不会构成问题。但是一旦我们有需求不通过浏览器来访问服务器的资源呢?那该怎么办呢?

    下面以本地客户端发起文件的上传、下载为例做个小Demo。HttpClient有两种形式,一种是org.apache.http下的,一种是org.apache.commons.httpclient.HttpClient。

2 文件上传

    文件上传可以使用两种方式实现,一种是PostMethod方式,一种是HttpPost方式。两者的处理大同小异。PostMethod是使用FileBody将文件包装流包装起来,HttpPost是使用FilePart将文件流包装起来。在传递文件流给服务端的时候,都可以同时传递其他的参数。

2.1 客户端处理

2.1.1 PostMethod方式

     将文件封装到FilePart中,放入Part数组,同时,其他参数可以放入StringPart中,这里没有写,只是单纯的将参数以setParameter的方式进行设置。此处的HttpClient是org.apache.commons.httpclient.HttpClient。

public void upload(String localFile){        File file = new File(localFile);        PostMethod filePost = new PostMethod(URL_STR);        HttpClient client = new HttpClient();                try {            // 通过以下方法可以模拟页面参数提交            filePost.setParameter("userName", userName);            filePost.setParameter("passwd", passwd);            Part[] parts = { new FilePart(file.getName(), file) };            filePost.setRequestEntity(new MultipartRequestEntity(parts, filePost.getParams()));                        client.getHttpConnectionManager().getParams().setConnectionTimeout(5000);                        int status = client.executeMethod(filePost);            if (status == HttpStatus.SC_OK) {                System.out.PRintln("上传成功");            } else {                System.out.println("上传失败");            }        } catch (Exception ex) {            ex.printStackTrace();        } finally {            filePost.releaseConnection();        }    }记得搞完之后,要通过releaseConnection释放连接。 

2.1.2 HttpPost方式

     这种方式,与上面类似,只不过变成了FileBody。上面的Part数组在这里对应HttpEntity。此处的HttpClient是org.apache.http.client.methods下的。

public void upload(String localFile){        CloseableHttpClient httpClient = null;        CloseableHttpResponse response = null;        try {            httpClient = HttpClients.createDefault();                        // 把一个普通参数和文件上传给下面这个地址 是一个servlet            HttpPost httpPost = new HttpPost(URL_STR);                        // 把文件转换成流对象FileBody            FileBody bin = new FileBody(new File(localFile));            StringBody userName = new StringBody("Scott", ContentType.create(                    "text/plain", Consts.UTF_8));            StringBody passWord = new StringBody("123456", ContentType.create(                    "text/plain", Consts.UTF_8));            HttpEntity reqEntity = MultipartEntityBuilder.create()                    // 相当于<input type="file" name="file"/>                    .addPart("file", bin)                                        // 相当于<input type="text" name="userName" value=userName>                    .addPart("userName", userName)                    .addPart("pass", password)                    .build();            httpPost.setEntity(reqEntity);            // 发起请求 并返回请求的响应            response = httpClient.execute(httpPost);                        System.out.println("The response value of token:" + response.getFirstHeader("token"));                            // 获取响应对象            HttpEntity resEntity = response.getEntity();            if (resEntity != null) {                // 打印响应长度                System.out.println("Response content length: " + resEntity.getContentLength());                // 打印响应内容                System.out.println(EntityUtils.toString(resEntity, Charset.forName("UTF-8")));            }                        // 销毁            EntityUtils.consume(resEntity);        }catch (Exception e){            e.printStackTrace();        }finally {            try {                if(response != null){                    response.close();                }            } catch (IOException e) {                e.printStackTrace();            }                        try {                if(httpClient != null){                    httpClient.close();                }            } catch (IOException e) {                e.printStackTrace();            }        }    }

2.2 服务端处理

     无论客户端是哪种上传方式,服务端的处理都是一样的。在通过HttpServletRequest获得参数之后,把得到的Item进行分类,分为普通的表单和File表单。    

     通过ServletFileUpload 可以设置上传文件的大小及编码格式等。

     总之,服务端的处理是把得到的参数当做HTML表单进行处理的。    

public void processUpload(HttpServletRequest request, HttpServletResponse response){        File uploadFile = new File(uploadPath);        if (!uploadFile.exists()) {            uploadFile.mkdirs();        }        System.out.println("Come on, baby .......");                request.setCharacterEncoding("utf-8");          response.setCharacterEncoding("utf-8");                    //检测是不是存在上传文件          boolean isMultipart = ServletFileUpload.isMultipartContent(request);                    if(isMultipart){              DiskFileItemFactory factory = new DiskFileItemFactory();                          //指定在内存中缓存数据大小,单位为byte,这里设为1Mb              factory.setSizeThreshold(1024*1024);                         //设置一旦文件大小超过getSizeThreshold()的值时数据存放在硬盘的目录               factory.setRepository(new File("D://temp"));                          // Create a new file upload handler              ServletFileUpload upload = new ServletFileUpload(factory);                         // 指定单个上传文件的最大尺寸,单位:字节,这里设为50Mb                upload.setFileSizeMax(50 * 1024 * 1024);                            //指定一次上传多个文件的总尺寸,单位:字节,这里设为50Mb              upload.setSizeMax(50 * 1024 * 1024);                 upload.setHeaderEncoding("UTF-8");                          List<FileItem> items = null;                            try {                  // 解析request请求                  items = upload.parseRequest(request);              } catch (FileUploadException e) {                  e.printStackTrace();              }                          if(items!=null){                  //解析表单项目                  Iterator<FileItem> iter = items.iterator();                  while (iter.hasNext()) {                      FileItem item = iter.next();                                         //如果是普通表单属性                      if (item.isFormField()) {                          //相当于input的name属性   <input type="text" name="content">                          String name = item.getFieldName();                                                //input的value属性                          String value = item.getString();                                                System.out.println("属性:" + name + " 属性值:" + value);                      }                      //如果是上传文件                      else {                          //属性名                          String fieldName = item.getFieldName();                                                  //上传文件路径                          String fileName = item.getName();                          fileName = fileName.substring(fileName.lastIndexOf("/") + 1);// 获得上传文件的文件名                                                  try {                              item.write(new File(uploadPath, fileName));                          } catch (Exception e) {                              e.printStackTrace();                          }                      }                 }              }          }                  response.addHeader("token", "hello");    }服务端在处理之后,可以在Header中设置返回给客户端的简单信息。如果返回客户端是一个流的话,流的大小必须提前设置!

    response.setContentLength((int) file.length());

3 文件下载

     文件的下载可以使用HttpClient的GetMethod实现,还可以使用HttpGet方式、原始的HttpURLConnection方式。

3.1 客户端处理

 3.1.1 GetMethod方式

    此处的HttpClient是org.apache.commons.httpclient.HttpClient。

public void downLoad(String remoteFileName, String localFileName) {        HttpClient client = new HttpClient();        GetMethod get = null;        FileOutputStream output = null;                try {            get = new GetMethod(URL_STR);            get.setRequestHeader("userName", userName);            get.setRequestHeader("passwd", passwd);            get.setRequestHeader("fileName", remoteFileName);            int i = client.executeMethod(get);            if (SUCCESS == i) {                System.out.println("The response value of token:" + get.getResponseHeader("token"));                File storeFile = new File(localFileName);                output = new FileOutputStream(storeFile);                                // 得到网络资源的字节数组,并写入文件                output.write(get.getResponseBody());            } else {                System.out.println("DownLoad file occurs exception, the error code is :" + i);            }        } catch (Exception e) {            e.printStackTrace();        } finally {            try {                if(output != null){                    output.close();                }            } catch (IOException e) {                e.printStackTrace();            }                        get.releaseConnection();            client.getHttpConnectionManager().closeIdleConnections(0);        }    }

3.1.2 HttpGet方式

    此处的HttpClient是org.apache.http.client.methods下的。

public void downLoad(String remoteFileName, String localFileName) {        DefaultHttpClient httpClient = new DefaultHttpClient();        OutputStream out = null;        InputStream in = null;                try {            HttpGet httpGet = new HttpGet(URL_STR);            httpGet.addHeader("userName", userName);            httpGet.addHeader("passwd", passwd);            httpGet.addHeader("fileName", remoteFileName);            HttpResponse httpResponse = httpClient.execute(httpGet);            HttpEntity entity = httpResponse.getEntity();            in = entity.getContent();            long length = entity.getContentLength();            if (length <= 0) {                System.out.println("下载文件不存在!");                return;            }            System.out.println("The response value of token:" + httpResponse.getFirstHeader("token"));            File file = new File(localFileName);            if(!file.exists()){                file.createNewFile();            }                        out = new FileOutputStream(file);              byte[] buffer = new byte[4096];            int readLength = 0;            while ((readLength=in.read(buffer)) > 0) {                byte[] bytes = new byte[readLength];                System.arraycopy(buffer, 0, bytes, 0, readLength);                out.write(bytes);            }                        out.flush();                    } catch (IOException e) {            e.printStackTrace();        } catch (Exception e) {            e.printStackTrace();        }finally{            try {                if(in != null){                    in.close();                }            } catch (IOException e) {                e.printStackTrace();            }                        try {                if(out != null){                    out.close();                }            } catch (IOException e) {                e.printStackTrace();            }        }    }

3.1.3 HttpURLConnection方式

public void download3(String remoteFileName, String localFileName) {        FileOutputStream out = null;        InputStream in = null;                try{            URL url = new URL(URL_STR);            URLConnection urlConnection = url.openConnection();            HttpURLConnection httpURLConnection = (HttpURLConnection) urlConnection;                        // true -- will setting parameters            httpURLConnection.setDoOutput(true);            // true--will allow read in from            httpURLConnection.setDoInput(true);            // will not use caches            httpURLConnection.setUseCaches(false);            // setting serialized            httpURLConnection.setRequestProperty("Content-type", "application/x-java-serialized-object");            // default is GET                                    httpURLConnection.setRequestMethod("POST");            httpURLConnection.setRequestProperty("connection", "Keep-Alive");            httpURLConnection.setRequestProperty("Charsert", "UTF-8");            // 1 min            httpURLConnection.setConnectTimeout(60000);            // 1 min            httpURLConnection.setReadTimeout(60000);            httpURLConnection.addRequestProperty("userName", userName);            httpURLConnection.addRequestProperty("passwd", passwd);            httpURLConnection.addRequestProperty("fileName", remoteFileName);            // connect to server (tcp)            httpURLConnection.connect();            in = httpURLConnection.getInputStream();// send request to                                                                // server            File file = new File(localFileName);            if(!file.exists()){                file.createNewFile();            }            out = new FileOutputStream(file);              byte[] buffer = new byte[4096];            int readLength = 0;            while ((readLength=in.read(buffer)) > 0) {                byte[] bytes = new byte[readLength];                System.arraycopy(buffer, 0, bytes, 0, readLength);                out.write(bytes);            }                        out.flush();        }catch(Exception e){            e.printStackTrace();        }finally{            try {                if(in != null){                    in.close();                }            } catch (IOException e) {                e.printStackTrace();            }                        try {                if(out != null){                    out.close();                }            } catch (IOException e) {                e.printStackTrace();            }        }    }

3.2 服务端处理

     尽管客户端的处理方式不同,但是服务端是一样的。

public void processDownload(HttpServletRequest request, HttpServletResponse response){        int BUFFER_SIZE = 4096;        InputStream in = null;        OutputStream out = null;                System.out.println("Come on, baby .......");                try{            request.setCharacterEncoding("utf-8");              response.setCharacterEncoding("utf-8");              response.setContentType("application/octet-stream");                        String userName = request.getHeader("userName");            String passwd = request.getHeader("passwd");            String fileName = request.getHeader("fileName");                        System.out.println("userName:" + userName);            System.out.println("passwd:" + passwd);            System.out.println("fileName:" + fileName);                        //可以根据传递来的userName和passwd做进一步处理,比如验证请求是否合法等                         File file = new File(downloadPath + "//" + fileName);            response.setContentLength((int) file.length());            response.setHeader("Accept-Ranges", "bytes");                        int readLength = 0;                        in = new BufferedInputStream(new FileInputStream(file), BUFFER_SIZE);            out = new BufferedOutputStream(response.getOutputStream());                        byte[] buffer = new byte[BUFFER_SIZE];            while ((readLength=in.read(buffer)) > 0) {                byte[] bytes = new byte[readLength];                System.arraycopy(buffer, 0, bytes, 0, readLength);                out.write(bytes);            }                        out.flush();                        response.addHeader("token", "hello 1");                     }catch(Exception e){            e.printStackTrace();             response.addHeader("token", "hello 2");        }finally {            if (in != null) {                try {                    in.close();                } catch (IOException e) {                }            }            if (out != null) {                try {                    out.close();                } catch (IOException e) {                }            }        }    }

4 小结

    HttpClient最基本的功能就是执行Http方法。一个Http方法的执行涉及到一个或者多个Http请求/Http响应的交互,通常这个过程都会自动被HttpClient处理,对用户透明。用户只需要提供Http请求对象,HttpClient就会将http请求发送给目标服务器,并且接收服务器的响应,如果http请求执行不成功,httpclient就会抛出异常。所以在写代码的时候注意finally的处理。    

    所有的Http请求都有一个请求列(request line),包括方法名、请求的URI和Http版本号。HttpClient支持HTTP/1.1这个版本定义的所有Http方法:GET,HEAD,POST,PUT,DELETE,TRACE和OPTIONS。上面的上传用到了Post,下载是Get。

    目前来说,使用org.apache.commons.httpclient.HttpClient多一些。看自己了~


发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表