HttpClient實現文件上傳功能

除瞭文件下載外,文件上傳也是項目開發中經常用到的功能。此時需要用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中制作文件管理器的知識和本示例程序結合起來,實現一個能夠通過圖形化方式選擇文件的文件上傳軟件。

以上就是本文的全部內容,希望對大傢的學習有所幫助,也希望大傢多多支持WalkonNet。

推薦閱讀: