1、事先了解

1.1 请求格式

我们使用http来上传文件,必须先了解http的请求格式,然后才好发报。主要分为以下四个部分:

1)分界符:由两个连字符“--”和任意字符串组成;

2)标准http报文格式,来形容上传文件的相关信息,包括请求参数名,上传文件名,文件类型,接收语言等。

3)上传文件的内容,通常是字节流的形式;

4)文件全部上传后的结束符:与分界符类似,只不过需要在分界符后面再加两个连字符。

1.2 http报文格式

1http请求报文

一个http请求报文格式是由四个部分组成,分别是请求行,请求头部,空行请求数据。其中需要注意的是空行 是必须的。

  1. 请求行

请求行是由请求方法、URL字段和HTTP协议版本这个3个部分组成。

请求方法有8个——

GET、POST、HEAD、PUT、DELETE、OPTIONS、TRACE、CONNECT

一般常用的就是GET POST 方法。

简单说下两者区别——

1GET

绝大部分的HTTP请求报文使用的是GET方法,如get这个单词本身含义一样,GET方法是用于获取查询资源信息,当浏览器请求一个对象时,使用GET方法。

2POST方法

HTTP客户机常常在用户提交表单时使用POST方法,需要用到实体主体。POST表示可能修改变服务器上的资源的请求

get请求可以获取静态页面,也可以把参数放在URL字串后面,传递给servlet

postget的不同之处在于post的参数不是放在URL字串里面,而是放在http请求的正文内。

URL字段就是"http://192.168.1.110:8080/abc"这种浏览器访问地址。

HTTP协议版本就是1.0 或者1.1 这两种其中之一。

  1. 请求头部

2Android 上传代码

httpUrlConnection URLConnection的子类,我们先来看看 URLConnection这个抽象类的相关介绍。注:以下内容来自 JDK API 1.6

抽象类URLConnection 是所有类的超类,它代表应用程序和 URL 之间的通信链接。此类的实例可用于读取和写入此 URL 引用的资源。通常,创建一个到 URL 的连接需要几个步骤:

openConnection()

connect()

对影响到远程资源连接的参数进行操作。

与资源交互;查询头字段和内容。

---------------------------->

时间

  1. 通过在 URL 上调用 openConnection 方法创建连接对象。
  1. 处理设置参数和一般请求属性。
  2. 使用 connect 方法建立到远程对象的实际连接。
  1. 远程对象变为可用。远程对象的头字段和内容变为可访问。

使用以下方法修改设置参数:

  • setAllowUserInteraction
  • setDoInput
  • setDoOutput
  • setIfModifiedSince
  • setUseCaches

使用以下方法修改一般请求属性:

  • setRequestProperty

使用setDefaultAllowUserInteraction setDefaultUseCaches 可设置 AllowUserInteraction UseCaches参数的默认值。

上面每个set 方法都有一个用于获取参数值或一般请求属性值的对应 get 方法。适用的具体参数和一般请求属性取决于协议。

在建立到远程对象的连接后,以下方法用于访问头字段和内容:

  • getContent
  • getHeaderField
  • getInputStream
  • getOutputStream

某些头字段需要经常访问。以下方法:

  • getContentEncoding
  • getContentLength
  • getContentType
  • getDate
  • getExpiration
  • getLastModifed

提供对这些字段的便捷访问。getContent方法使用 getContentType 方法以确定远程对象类型;子类重写 getContentType 方法很容易。

一般情况下,所有的预连接参数和一般请求属性都可忽略:预连接参数和一般请求属性默认为敏感值。对于此接口的大多数客户端而言,只有两个需要的方法:getInputStreamgetContent,它们通过便捷方法镜像到 URL 类中。

API上对 HttpURLConnection 的介绍是:

每个HttpURLConnection 实例都可用于生成单个请求,但是其他实例可以透明地共享连接到 HTTP 服务器的基础网络。请求后在HttpURLConnection InputStream OutputStream 上调用 close() 方法可以释放与此实例关联的网络资源,但对共享的持久连接没有任何影响。如果在调用 disconnect() 时持久连接空闲,则可能关闭基础套接字。

因此,由上可知,HttpURLConnectionjava用于特定的HTTP通信的类。通过使用HttpURLConnection对象的方法设置相关参数,我们就能进行http通信。

1public void setDoInput(boolean doinput) 方法

如果打算使用 URL 连接进行输入,则将 DoInput 标志设置为 true;如果不打算使用,则设置为 false。默认值为true。

2public void setDoOutput(boolean dooutput)

将此 URLConnection doOutput 字段的值设置为指定的值。

URL 连接可用于输入和/或输出。如果打算使用 URL 连接进行输出,则将 DoOutput标志设置为 true;如果不打算使用,则设置为 false。默认值为 false

3public void setUseCaches(boolean usecaches)

将此 URLConnection useCaches 字段的值设置为指定的值。

有些协议用于文档缓存。有时候能够进行“直通”并忽略缓存尤其重要,例如浏览器中的“重新加载”按钮。如果连接中的UseCaches 标志为 true,则允许连接使用任何可用的缓存。如果为 false,则忽略缓存。默认值来自 DefaultUseCaches,它默认为 true

具体代码如下:

/* 上传文件至Server的方法 */private void uploadFile() {String end = "\r\n";String twoHyphens = "--";String boundary = "*****";String newName = "image.jpg";String uploadFile = "storage/sdcard1/bagPictures/102.jpg";;String actionUrl = "http://192.168.1.123:8080/upload/servlet/UploadServlet";try {URL url = new URL(actionUrl);HttpURLConnection con = (HttpURLConnection) url.openConnection();/* 允许Input、Output,不使用Cache */con.setDoInput(true);con.setDoOutput(true);con.setUseCaches(false);/* 设置传送的method=POST */con.setRequestMethod("POST");/* setRequestProperty */con.setRequestProperty("Connection", "Keep-Alive");con.setRequestProperty("Charset", "UTF-8");con.setRequestProperty("Content-Type","multipart/form-data;boundary=" + boundary);/* 设置DataOutputStream */DataOutputStream ds = new DataOutputStream(con.getOutputStream());ds.writeBytes(twoHyphens + boundary + end);ds.writeBytes("Content-Disposition: form-data; "+ "name=\"file1\";filename=\"" + newName + "\"" + end);ds.writeBytes(end);/* 取得文件的FileInputStream */FileInputStream fStream = new FileInputStream(uploadFile);/* 设置每次写入1024bytes */int bufferSize = 1024;byte[] buffer = new byte[bufferSize];int length = -1;/* 从文件读取数据至缓冲区 */while ((length = fStream.read(buffer)) != -1) {/* 将资料写入DataOutputStream中 */ds.write(buffer, 0, length);}ds.writeBytes(end);ds.writeBytes(twoHyphens + boundary + twoHyphens + end);/* close streams */fStream.close();ds.flush();/* 取得Response内容 */InputStream is = con.getInputStream();int ch;StringBuffer b = new StringBuffer();while ((ch = is.read()) != -1) {b.append((char) ch);}/* 将Response显示于Dialog */showDialog("上传成功" + b.toString().trim());/* 关闭DataOutputStream */ds.close();} catch (Exception e) {showDialog("上传失败" + e);}}

3、服务器端的代码

public class UploadServlet extends HttpServlet {public void doGet(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException {try {System.out.println("IP:" + request.getRemoteAddr());// 1、创建工厂类:DiskFileItemFactoryDiskFileItemFactory facotry = new DiskFileItemFactory();String tempDir = getServletContext().getRealPath("/WEB-INF/temp");facotry.setRepository(new File(tempDir));//设置临时文件存放目录// 2、创建核心解析类:ServletFileUploadServletFileUpload upload = new ServletFileUpload(facotry);upload.setHeaderEncoding("UTF-8");// 解决上传的文件名乱码upload.setFileSizeMax(1024 * 1024 * 1024);// 单个文件上传最大值是1Mupload.setSizeMax(2048 * 1024 * 1024);//文件上传的总大小限制// 3、判断用户的表单提交方式是不是multipart/form-databoolean bb = upload.isMultipartContent(request);if (!bb) {return;}// 4、是:解析request对象的正文内容List<FileItem>List<FileItem> items = upload.parseRequest(request);String storePath = getServletContext().getRealPath("/WEB-INF/upload");// 上传的文件的存放目录for (FileItem item : items) {if (item.isFormField()) {// 5、判断是否是普通表单:打印看看String fieldName = item.getFieldName();// 请求参数名String fieldValue = item.getString("UTF-8");// 请求参数值System.out.println(fieldName + "=" + fieldValue);} else {// 6、上传表单:得到输入流,处理上传:保存到服务器的某个目录中,保存时的文件名是啥?String fileName = item.getName();// 得到上传文件的名称 C:\Documents// and// Settings\shc\桌面\a.txt// a.txt//解决用户没有选择文件上传的情况if(fileName==null||fileName.trim().equals("")){continue;}fileName = fileName.substring(fileName.lastIndexOf("\\") + 1);String newFileName = UUIDUtil.getUUID() + "_" + fileName;System.out.println("上传的文件名是:" + fileName);InputStream in = item.getInputStream();String savePath = makeDir(storePath, fileName) + "\\"+ newFileName;OutputStream out = new FileOutputStream(savePath);byte b[] = new byte[1024];int len = -1;while ((len = in.read(b)) != -1) {out.write(b, 0, len);}in.close();out.close();item.delete();//删除临时文件}}}catch(FileUploadBase.FileSizeLimitExceededException e){request.setAttribute("message", "单个文件大小不能超出5M");request.getRequestDispatcher("/message.jsp").forward(request,response);}catch(FileUploadBase.SizeLimitExceededException e){request.setAttribute("message", "总文件大小不能超出7M");request.getRequestDispatcher("/message.jsp").forward(request,response);}catch (Exception e) {e.printStackTrace();request.setAttribute("message", "上传失败");request.getRequestDispatcher("/message.jsp").forward(request,response);}}// WEB-INF/upload/1/3 打散存储目录private String makeDir(String storePath, String fileName) {int hashCode = fileName.hashCode();// 得到文件名的hashcode码int dir1 = hashCode & 0xf;// 取hashCode的低4位 0~15int dir2 = (hashCode & 0xf0) >> 4;// 取hashCode的高4位 0~15String path = storePath + "\\" + dir1 + "\\" + dir2;File file = new File(path);if (!file.exists())file.mkdirs();System.out.println("存储路径是"+path);return path;}public void doPost(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException {doGet(request, response);}}

4、实验结果

用httpUrlConnection实现文件上传相关推荐

  1. android使用HttpURLConnection/HttpClient实现带参数文件上传

    本文参考自[http://blog.csdn.net/crazy__chen/article/details/47703781] 在Android 2.3及以上版本,使用的是HttpURLConnec ...

  2. Android 实现文件上传功能(upload)

    文 件上传在B/S应用中是一种十分常见的功能,那么在Android平台下是否可以实现像B/S那样的文件上传功能呢?答案是肯定的.下面是一个模拟网站程 序上传文件的例子.这里只写出了Android部分的 ...

  3. Android Day05-网络编程之文件上传

    Android文件上传实现 分析:利用抓包工具查看文件上传发现,文件上传的请求体十分的复杂,根本难以用 HttpURLConnection.HttpClient来实现.但是用AsyncHttpClie ...

  4. php 上传sb2,基于标准的http来实现Android多文件上传

    实现多文件的上传,基于标准的http来实现. 多文件上传MyUploader类的实现: /** * * 同步上传多个文件 * 基于标准的http实现,需要在非UI线程中调用,以免阻塞UI. * */ ...

  5. HttpURLConnection_Get和Post请求文件上传

    本博文为子墨原创,转载请注明出处! http://blog.csdn.net/zimo2013/article/details/9469543 关于HttpClient用法 1.HttpURLConn ...

  6. 超详细的实现上传文件功能教程,文件上传实现。

    重要声明:本文章仅仅代表了作者个人对此观点的理解和表述.读者请查阅时持自己的意见进行讨论. 本文更新不及时,请到原文地址浏览:<超详细的实现上传文件功能教程,文件上传实现.>. 一.文件上 ...

  7. android之文件上传

    文件上传 android中的文件上传使用的是post的提交方式. 通过httpwatcher抓一个文件上传时的包,可以更加好的明白下面的代码 //调用此方法时需要传递用户名,密码,文件路径 文件上传时 ...

  8. Android 文件上传的几种方式

    这两天和新来的同事做一个项目,用到了文件上传,在这里记录下历程 Android文件上传有各种各样的Http框架,我也就简单说说我常用的吧,LiteHttp,OkHttp的封装还没做完全,有时间会补上, ...

  9. Android + https 实现 文件上传

    Android 应用中,如何使用https 实现 文件上传功能. package com.example.wbdream.zigvine;import android.annotation.Suppr ...

最新文章

  1. FBL3N增加表字段
  2. 设置mysql最大连接数的方法
  3. Jerry Wang一篇介绍ABAP调试心得的博客上了SAP社区的首页
  4. 【刷题】BZOJ 4657 tower
  5. 如何在Java中转义JSON字符串-Eclipse IDE技巧
  6. android ndk 9,Android NDK:警告:APP_PLATFORM android-9大于android:minSdkVersion 8
  7. 网络负载均衡适用场景
  8. 修改完/etc/fstab后重新挂载方法
  9. 【CDH】ClouderaManager集群报警,堆转储目录/tmp 或日志目录/var/log 可用空间小于 5.0 吉字节
  10. MySQL Semisync
  11. Activity与Fragment的onActivityResult细节
  12. Android_getevent工具的使用
  13. pytorch加载自己的数据集图片格式
  14. 记录:ubuntu安装zlog及使用
  15. 保定学院计算机编程,惠普HP打印机驱动程序安装失败怎么办hewlett-packard上的文件...
  16. 贴吧手工自动发帖软件
  17. 天津大学计算机组成原理,天津大学计算机学院计算机组成原理复习材料.docx
  18. 目标跟踪:在视频序列中跟踪特定对象的位置和状态
  19. 微信小程序云开发:使用cms平台来创建json数组
  20. 字节、字、bit、byte到底咋回事

热门文章

  1. 基础:cin与char*的相关问题
  2. 【思维导图】巩固你的JavaScript知识体系
  3. wordpress采集插件支持任意wordpress主题
  4. 人物-发明家-爱迪生:*托马斯·阿尔瓦·爱迪生
  5. python3 ACM模式的输入输出例子教学
  6. MT7621_基础篇(1) 芯片资料了解 一
  7. SAP如何将物料账期跨年月一次性开到当前
  8. 计算机组成原理题目透析(2)
  9. Foods Keep Younger, Strong And Healthy
  10. 移动电源充电宝新国标GB/T 35590-2017检测报告测试项目