Android笔记(三):整理——利用http上传小文件

来源:互联网 发布:淘宝买到假酒怎么办 编辑:程序博客网 时间:2024/06/15 18:09

本文记录如何使用rfc1867协议来上传文本文件(大小不能超过2M)


首先客户端上传文件时,服务器要收到客户端的请求就必须在客户端人工构造rfc1867协议规定的请求内容。

具体如下:

--UUID

Content-Disposition:form-data;name="字段名"

Content-Type:text/plain;charset=UTF-8       //如果上传的不是文本文件而是图片,则text/plain改为image/jpeg

Content-Transfer-Enconding:8dit       //所传送的内容不符合默认的编码方式,须加上该标题头

字段属性值

--UUID

Content-Disposition:form-data;name="字段名";filename="文件名"

Content-Type:application/octet-stream;charset=UTF-8

文件内容(二进制流)

--UUID--        //最后要加上回车   


其中UUID是随机生成的一串数字,作为分隔符。


下面是客户端的实现:

public class FileUploadActivity extends Activity {    @Override    protected void onCreate(@Nullable Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        StrictMode                .setThreadPolicy(new StrictMode.ThreadPolicy.Builder()                        .detectDiskReads().detectDiskWrites()                        .detectNetwork().penaltyLog().build());        StrictMode.setVmPolicy(new StrictMode.VmPolicy.Builder()                .detectLeakedSqlLiteObjects()                .detectLeakedClosableObjects().penaltyLog()                .penaltyDeath().build());        Button button = new Button(this);
        button.setText("上传");        setContentView(button);        button.setOnClickListener(new View.OnClickListener() {            @Override            public void onClick(View v) {                final String actionUrl = "http://36078d58.nat123.cc/FileUploadAndDownload/UploadHandleServlet";                final Map<String, String> params = new HashMap<>();                params.put("strParamName", "strParamValue");                final Map<String, File> files = new HashMap<>();                files.put("android上传.txt", new File("/storage/emulated/0/eguan.txt"));  // key为上传后的文件名,value为要上传的文件路径                new Thread(new Runnable() {                    @Override                    public void run() {                        try {                            String str = post(actionUrl, params, files);                            Log.d("FileUploadActivity", "结果:" + str);                        } catch (Exception e) {                            e.printStackTrace();                        }                    }                }).start();            }        });    }    public static String post(String actionUrl,                              Map<String, String> params, Map<String, File> files)            throws IOException {        String BOUNDARY = java.util.UUID.randomUUID().toString();        String PREFIX = "--", LINEND = "\r\n";        String MULTIPART_FROM_DATA = "multipart/form-data";        String CHARSET = "UTF-8";        URL uri = new URL(actionUrl);        HttpURLConnection conn = (HttpURLConnection) uri                .openConnection();        conn.setReadTimeout(5 * 1000); // 缓存的最长时间        conn.setDoInput(true);// 允许输入        conn.setDoOutput(true);// 允许输出        conn.setUseCaches(false); // 不允许使用缓存        conn.setRequestMethod("POST");        conn.setRequestProperty("connection", "keep-alive");   //保持连接活跃        conn.setRequestProperty("Charset", "UTF-8");        conn.setRequestProperty("Content-Type", MULTIPART_FROM_DATA                + ";boundary=" + BOUNDARY);        // 首先组拼文本类型的参数        StringBuilder sb = new StringBuilder();        for (Map.Entry<String, String> entry : params.entrySet()) {            sb.append(PREFIX);            sb.append(BOUNDARY);            sb.append(LINEND);            sb.append("Content-Disposition: form-data; name=\""                    + entry.getKey() + "\"" + LINEND);            sb.append("Content-Type: text/plain; charset="                    + CHARSET + LINEND);            sb.append("Content-Transfer-Encoding: 8bit" + LINEND);            sb.append(LINEND);            sb.append(entry.getValue());            sb.append(LINEND);        }        DataOutputStream outStream = new DataOutputStream(                conn.getOutputStream());        outStream.write(sb.toString().getBytes());        // 发送文件数据        if (files != null)            for (Map.Entry<String, File> file : files.entrySet()) {                StringBuilder sb1 = new StringBuilder();                sb1.append(PREFIX);                sb1.append(BOUNDARY);                sb1.append(LINEND);                sb1.append("Content-Disposition: form-data; name=\"file\"; filename=\""                        + file.getKey() + "\"" + LINEND);                sb1.append("Content-Type: application/octet-stream; charset="                        + CHARSET + LINEND);                sb1.append(LINEND);                outStream.write(sb1.toString().getBytes());                InputStream is = new FileInputStream(file.getValue());                byte[] buffer = new byte[1024];                int len;                while ((len = is.read(buffer)) != -1) {                    outStream.write(buffer, 0, len);                }                is.close();                outStream.write(LINEND.getBytes());            }        // 请求结束标志        byte[] end_data = (PREFIX + BOUNDARY + PREFIX + LINEND)                .getBytes();        outStream.write(end_data);        outStream.flush();        // 得到响应码        int res = conn.getResponseCode();        StringBuilder sb2 = null;        InputStream in = conn.getInputStream();        if (res == 200) {            int ch;            sb2 = new StringBuilder();            while ((ch = in.read()) != -1) {                sb2.append((char) ch);            }        }        outStream.close();        conn.disconnect();        if (sb2==null)            return null;        else            return sb2.toString();    }}


注:

①真机测试

服务端与客户端不在同一个局域网,访问需要外网ip地址映射,如本文为:http://36078d58.nat123.cc/FileUploadAndDownload/UploadHandleServlet;客户端和服务端处在同一个局域网,则可将36078d58.nat123.cc改为服务端所在计算机的局域网ip地址,如192.168.x.x:8080。

②模拟器测试

客户端是android自带的模拟器的,ip改为10.0.2.2:8080;是第三方模拟器的,ip改为服务端所在计算机的ip地址。

下面是服务端的实现:

在eclipse下新建一个web项目,名为FileUploadAndDownload,在src目录下新建一个包,在包内新建一个java文件,名为UploadHandleServlet.java,然后将项目打包成war文件放到Tomcat服务器所在目录下的webapps文件夹内,并启动Tomcat。

@WebServlet("/UploadHandleServlet")public class UploadHandleServlet extends HttpServlet {private static final long serialVersionUID = 1L;/** * @see HttpServlet#HttpServlet() */public UploadHandleServlet() {super();// TODO Auto-generated constructor stub}/** * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse *      response) */protected void doGet(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException {// TODO Auto-generated method stub// 得到上传文件的保存目录,将上传的文件存放于WEB-INF目录下,不允许外界直接访问,保证上传文件的安全String savePath = this.getServletContext().getRealPath("/WEB-INF/upload");File file = new File(savePath);// 判断上传文件的保存目录是否存在if (!file.exists() && !file.isDirectory()) {System.out.println(savePath + "目录不存在,需要创建");// 创建目录file.mkdir();}// 消息提示String message = "";try {// 使用Apache文件上传组件处理文件上传步骤:// 1、创建一个DiskFileItemFactory工厂DiskFileItemFactory factory = new DiskFileItemFactory();// 2、创建一个文件上传解析器ServletFileUpload upload = new ServletFileUpload(factory);// 解决上传文件名的中文乱码upload.setHeaderEncoding("UTF-8");// 3、判断提交上来的数据是否是上传表单的数据if (!ServletFileUpload.isMultipartContent(request)) {// 按照传统方式获取数据return;}// 4、使用ServletFileUpload解析器解析上传数据,解析结果返回的是一个List<FileItem>集合,每一个FileItem对应一个Form表单的输入项List<FileItem> list = upload.parseRequest(request);for (FileItem item : list) {// 如果fileitem中封装的是普通输入项的数据if (item.isFormField()) {String name = item.getFieldName();// 解决普通输入项的数据的中文乱码问题String value = item.getString("UTF-8");// value = new String(value.getBytes("GB2312"),"UTF-8");System.out.println(name + "=" + value);} else {// 如果fileitem中封装的是上传文件// 得到上传的文件名称,String filename = item.getName();System.out.println(filename);if (filename == null || filename.trim().equals("")) {continue;}// 注意:不同的浏览器提交的文件名是不一样的,有些浏览器提交上来的文件名是带有路径的,如:// c:\a\b\1.txt,而有些只是单纯的文件名,如:1.txt// 处理获取到的上传文件的文件名的路径部分,只保留文件名部分filename = filename.substring(filename.lastIndexOf("\\") + 1);// 获取item中的上传文件的输入流InputStream in = item.getInputStream();// 创建一个文件输出流FileOutputStream out = new FileOutputStream(savePath + "\\" + filename);// 创建一个缓冲区byte buffer[] = new byte[1024];// 判断输入流中的数据是否已经读完的标识int len = 0;// 循环将输入流读入到缓冲区当中,(len=in.read(buffer))>0就表示in里面还有数据while ((len = in.read(buffer)) > 0) {// 使用FileOutputStream输出流将缓冲区的数据写入到指定的目录(savePath + "\\"// + filename)当中out.write(buffer, 0, len);}// 关闭输入流in.close();// 关闭输出流out.close();// 删除处理文件上传时生成的临时文件item.delete();message = "文件上传成功!";}}} catch (Exception e) {message = "文件上传失败!";e.printStackTrace();}request.setAttribute("message", message);request.getRequestDispatcher("/message.jsp").forward(request, response);}/** * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse *      response) */protected void doPost(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException {// TODO Auto-generated method stubRequestContext req = new ServletRequestContext(request);if (FileUpload.isMultipartContent(req)) {DiskFileItemFactory factory = new DiskFileItemFactory();ServletFileUpload fileUpload = new ServletFileUpload(factory);fileUpload.setHeaderEncoding("UTF-8");fileUpload.setFileSizeMax(1024 * 1024 * 1024);List items = new ArrayList();try {items = fileUpload.parseRequest(request);} catch (Exception e) {}Iterator it = items.iterator();while (it.hasNext()) {FileItem fileItem = (FileItem) it.next();if (fileItem.isFormField()) {System.out.println(fileItem.getFieldName() + " " + fileItem.getName() + " "+ new String(fileItem.getString().getBytes("UTF-8"), "UTF-8"));} else {System.out.println(fileItem.getFieldName() + " " + fileItem.getName() + " " + fileItem.isInMemory()+ " " + fileItem.getContentType() + " " + fileItem.getSize());if (fileItem.getName() != null && fileItem.getSize() != 0) {File fullFile = new File(fileItem.getName());File newFile = new File("D:\\" + fullFile.getName());try {fileItem.write(newFile);} catch (Exception E) {}response.getWriter().write("Success!");} else {System.out.println("no file choosen or empty file");response.getWriter().print("Failure!");}}}}}}

注:客户端发送文件上传请求后会调用doPost方法,上传后的文件会保存在D盘,上传成功后会返回结果给客户端。doPost部分代码的解释可参照doGet

阅读全文
0 0
原创粉丝点击