HttpClient实现文件上传功能


Posted in Java/Android onAugust 14, 2022

除了文件下载外,文件上传也是项目开发中经常用到的功能。此时需要用HttpClient类库的扩展包HttpMime中的MultipartEntity类,此类同样实现了HttpEntity接口。需要注意的是HttpClient通过POST来上传文件,而不是通过流的形式。

示例:使用HttpClient实现文件上传功能。

第一步:要求在服务器端使用fileupload组件接收客户端提交内容。新建一个JSP项目zghc,首先在WEB-INF/lib目录下加入commons-fileupload-1.2.2.jar和commons-io-2.4.jar两个jar包,然后再提供一个对用户提交数据(文本、文件)进行处理的Servlet,具体代码如下所示:

@WebServlet("/uploadServlet")
public class UploadServlet extends HttpServlet {    // 使用fileupload组件
    private static final long serialVersionUID = 1L;
    protected void doPost(HttpServletRequest request,
            HttpServletResponse response) throws ServletException, IOException {
        // 检测是不是文件上传的请求
        boolean isMultipart = ServletFileUpload.isMultipartContent(request);
        if (isMultipart) {// 属于上传文件的请求
            // 创建磁盘工厂,该类用来配置上传组件ServletFileUpload
            DiskFileItemFactory factory = new DiskFileItemFactory();
            factory.setSizeThreshold(10 * 1024 * 1024);
            factory.setRepository(new File("D:/")); // 设置存放临时文件的目录
            // 使用磁盘工厂实例化上传组件
            ServletFileUpload upload = new ServletFileUpload(factory);
            upload.setSizeMax(10 * 1024 * 1024); // 设置允许的最大上传尺寸
            upload.setHeaderEncoding("UTF-8");// 明确指定使用UTF-8编码
            PrintWriter out = response.getWriter();
            try {    // 获取客户端提交过来的所有请求参数
                List<FileItem> items = upload.parseRequest(request); // 解析
                for (FileItem item : items) {//对用户上传的所有文件进行遍历
                    if (item.isFormField()) {// 如果是表单字段
                        System.out.println(item.getFieldName()+"  "+
item.getString("UTF-8"));
                    } else {// 如果是文件
                        String path = request.getSession().getServletContext()
                                .getRealPath("/");// 站点根目录的路径
                        String name = item.getName().substring(
                                item.getName().lastIndexOf("/") + 1); // ---②
                        // 保存用户上传的文件到指定目录
                        item.write(new File(path, name)); 
                        System.out.println("上传完毕");
                        response.setCharacterEncoding("UTF-8");
                        out.println("上传完毕");
                    }
                }
            } catch (Exception e) {
                e.printStackTrace();
                out.println("文件超过规定大小");
            }
        }
    }
}

FileItemFactory类的setSizeThreshold()方法用来设置上传文件时用于临时存放文件的内存的大小,超出的部分将临时存放在硬盘,可以使用FileItemFactory类的 setRepository()方法设置临时文件的目录。

在调用item.write()方法写入数据到文件中时,如果文件的名称是中文,有可能会出现乱码;另外需要注意的是Windows系统中item.getName()方法的返回的值是带路径的。

提示:

如果使用tomcat6,采用传统的在web.xml方式中配置Servlet,编号②处的代码需要改为:item.getName().lastIndexOf("\")
第二步:提供一个JSP文件upload.jsp,对上面的Servlet进行测试。注意在此JSP文件中需要设置form表单的enctype的值为multipart/form-data。

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
    <head>
        <title>My JSP 'index.jsp' starting page</title>
    </head>
    <body>
        <form action="uploadServlet" method="post" enctype="multipart/form-data">
            标题:<input type="text" name="name"/>
            文件:<input type="file" name="imgFile"/>
            <input type="submit" value="提交"/>
        </form>
    </body>
</html>

为了能上传文件,必须将表单的method属性设置为POST、enctype属性设置为multipart/form-data,只有这样,浏览器才会把用户选择文件的二进制数据发送给服务器。

第四步:将上面的JSP项目部署到tomcat中,然后在打开的upload.jsp页面中输入文件名,选中要上传的文件,单击【提交】按钮,然后在tomcat下的webapps\zghc目录下确实发现上传的文件,表明文件上传成功。

第五步:新建一个Android项目,将httpmime_XXXX.jar文件添加到当前项目的classpath路径下面,然后在项目中添加一个实现上传功能的工具类,具体代码如下所示:

public class HttpClientUtil {
    public static HttpClient httpClient = new DefaultHttpClient();
    public static String sendPost(String url,HashMap<String,String> map,File file){
        String result = null;
        HttpPost post = new HttpPost(url);// 创建HttpPost对象
        // 如果传递参数个数比较多的话可以对传递的参数进行封装
        MultipartEntity entity = new MultipartEntity();
        try {
            for (String key : map.keySet()) {    // 封装请求参数
StringBody value = new StringBody(map
                        .get(key), Charset.forName("UTF-8"));//避免传递汉字出现乱码
                entity.addPart(new FormBodyPart(key,value));
            }
            if(file != null)
                entity.addPart("myfile", new FileBody(file));
            post.setEntity(entity);// 设置请求参数
            synchronized (httpClient) {
                HttpResponse response = httpClient.execute(post);// 发送POST请求
                if (response.getStatusLine().getStatusCode() == 200){
                    HttpEntity resEntity = response.getEntity();
                    result = EntityUtils.toString(resEntity, "UTF-8");
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        return result;
    }
}

第六步:为了提高用户体验,我们提供一个线程类来实现文件文件上传的功能,具体代码如下所示:

public class UploadThread extends Thread {
    private String url;
    private HashMap<String, String> map;
    private File file;
    private Handler handler;
    public UploadThread(String url, HashMap<String, String> map, File file,
            Handler handler) {
        this.url = url;
        this.map = map;
        this.file = file;
        this.handler = handler;
    }
    @Override
    public void run() {
        String result = HttpClientUtil.sendPost(url, map, file);  //具体上传代码
        System.out.println("aaaaa" + result);
        if ("上传完毕".equals(result.trim())) {
            handler.sendEmptyMessage(1);
        } else {
            handler.sendEmptyMessage(0);
        }
    }
}

第七步:在主布局文件中提供一个onClick属性值为upload的Button,然后修改MainAcvitity类的代码如下所示:

public class MainActivity extends Activity {
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    }
    private Handler handler = new Handler() {
        public void handleMessage(Message msg) {
            if (msg.what == 1) {
                Toast.makeText(MainActivity.this, "提交数据成功", 1).show();
            } else {
                Toast.makeText(MainActivity.this, "提交数据失败", 1).show();
            }
        }
    };
    public void upload(View view) {
        HashMap<String, String> map = new HashMap<String, String>();
        map.put("username", "music");
        File sdPath = Environment.getExternalStorageDirectory();
        File file = new File(sdPath + "/zbjbxf.mp3");
        String url = "http://10.0.2.2:8080/zghc/uploadServlet";
        UploadThread thread = new UploadThread(url, map, file, handler);
        thread.start();
    }
}

在保证第一步创建的JSP项目已经部署到tomcat中且tomcat已经启动的前提下,运行本程序,发现当点击客户端主界面中的Button按钮后,在tomcat下的webapps/zghc目录下确实看到了刚才上传的文件。

大家可以将前面章节中学到Android中制作文件管理器的知识和本示例程序结合起来,实现一个能够通过图形化方式选择文件的文件上传软件。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Java/Android 相关文章推荐
Spring Cache和EhCache实现缓存管理方式
Jun 15 Java/Android
Java实现简易的分词器功能
Jun 15 Java/Android
详解Spring事件发布与监听机制
Jun 30 Java/Android
浅谈resultMap的用法及关联结果集映射
Jun 30 Java/Android
解决MultipartFile.transferTo(dest) 报FileNotFoundExcep的问题
Jul 01 Java/Android
解决Swagger2返回map复杂结构不能解析的问题
Jul 02 Java/Android
Java Spring 控制反转(IOC)容器详解
Oct 05 Java/Android
Spring this调用当前类方法无法拦截的示例代码
Mar 20 Java/Android
java如何实现获取客户端ip地址的示例代码
Apr 07 Java/Android
Spring IOC容器Bean的作用域及生命周期实例
May 30 Java/Android
java.util.NoSuchElementException原因及两种解决方法
Jun 28 Java/Android
AndroidStudio图片压缩工具ImgCompressPlugin使用实例
Aug 05 Java/Android
SpringBoot Http远程调用的方法
Aug 14 #Java/Android
基于Android10渲染Surface的创建过程
Aug 14 #Java/Android
OpenFeign实现远程调用
Aug 14 #Java/Android
httpclient调用远程接口的方法
Aug 14 #Java/Android
Java Spring读取和存储详细操作
Aug 05 #Java/Android
AndroidStudio图片压缩工具ImgCompressPlugin使用实例
Aug 05 #Java/Android
Java代码规范与质量检测插件SonarLint的使用
Aug 05 #Java/Android
You might like
PHP 多维数组排序(usort,uasort)
2010/06/30 PHP
让php处理图片变得简单 基于gb库的图片处理类附实例代码下载
2011/05/17 PHP
Apache服务器无法使用的解决方法
2013/05/08 PHP
PHP模板引擎Smarty的缓存使用总结
2014/04/24 PHP
PHP处理会话函数大总结
2015/08/05 PHP
ThinkPHP的SAE开发相关注意事项详解
2016/10/09 PHP
PHP实现的多进程控制demo示例
2019/07/22 PHP
event.srcElement+表格应用
2006/08/29 Javascript
javascript常见操作汇总
2014/09/03 Javascript
浅谈JavaScript字符串拼接
2015/06/25 Javascript
jQuery网页选项卡插件rTabs用法实例分析
2015/08/26 Javascript
网页从弹窗页面单选框传值至父页面代码分享
2015/09/29 Javascript
jquery $.trim()去除字符串空格的实现方法【附图例】
2016/03/30 Javascript
jquery.serialize() 函数语法及简单实例
2016/07/08 Javascript
详解JavaScript 中getElementsByName在IE中的注意事项
2017/02/21 Javascript
js判断手机系统是android还是ios
2017/03/07 Javascript
canvas实现爱心和彩虹雨效果
2017/03/09 Javascript
对于js垃圾回收机制的理解
2017/09/14 Javascript
Node.js上传文件功能之服务端如何获取文件上传进度
2018/02/05 Javascript
Vue下拉框回显并默认选中随机问题
2018/09/06 Javascript
Vue的props父传子的示例代码
2020/05/20 Javascript
解决antd datepicker 获取时间默认少8个小时的问题
2020/10/29 Javascript
解决python给列表里添加字典时被最后一个覆盖的问题
2019/01/21 Python
python绘制多个子图的实例
2019/07/07 Python
Python 处理日期时间的Arrow库使用
2020/08/18 Python
详解CSS3选择器的使用方法汇总
2015/11/24 HTML / CSS
IE8下CSS3选择器nth-child() 不兼容问题的解决方法
2016/11/16 HTML / CSS
使用html5 canvas创建太空游戏的示例
2014/05/08 HTML / CSS
澳大利亚购买最佳炊具品牌网站:Cookware Brands
2019/02/16 全球购物
法国一家多品牌成衣精品中/高档商店:Graduate Store
2019/08/28 全球购物
银行介绍信范文
2014/01/10 职场文书
暑期社会实践方案
2014/02/05 职场文书
竞争与合作演讲稿
2014/05/12 职场文书
2014年医生工作总结
2014/11/21 职场文书
2015纪念九一八事变84周年演讲稿
2015/03/19 职场文书
让人感觉高大上的讲话稿怎么写?
2019/07/08 职场文书