用httpUrlConnection实现文件上传

1、事先了解

1.1
请求格式

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

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

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

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

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

1.2 http报文格式

(1)http请求报文

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

  1. 请求行

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

请求方法有8个——

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

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

简单说下两者区别——

(1)GET

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

(2)POST方法

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

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

post与get的不同之处在于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
方法很容易。

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

而API上对 HttpURLConnection
的介绍是:

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

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

(1)public
void setDoInput(boolean doinput)
方法

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

(2)public
void setDoOutput(boolean dooutput)

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

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

(3)public
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、创建工厂类:DiskFileItemFactory
			DiskFileItemFactory facotry = new DiskFileItemFactory();
			String tempDir = getServletContext().getRealPath("/WEB-INF/temp");
			facotry.setRepository(new File(tempDir));//设置临时文件存放目录
			// 2、创建核心解析类:ServletFileUpload
			ServletFileUpload upload = new ServletFileUpload(facotry);
			upload.setHeaderEncoding("UTF-8");// 解决上传的文件名乱码
			upload.setFileSizeMax(1024 * 1024 * 1024);// 单个文件上传最大值是1M
			upload.setSizeMax(2048 * 1024 * 1024);//文件上传的总大小限制

			// 3、判断用户的表单提交方式是不是multipart/form-data
			boolean 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~15
		int dir2 = (hashCode & 0xf0) >> 4;// 取hashCode的高4位 0~15
		String 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实现文件上传,布布扣,bubuko.com

时间: 2024-10-25 18:02:12

用httpUrlConnection实现文件上传的相关文章

Volley源码分析之自定义MultiPartRequest(文件上传)

本篇内容目录: 使用HttpURLConnection上传文件到服务器案例 自定义支持文件上传的MultiPartRequest Web后台接收文件的部分代码 先来看下HttpURLConnection来文件上传的案例: 1.传送数据到服务器,必定是使用POST请求: //设置请求方式为post httpURLConnection.setDoOutput(true); httpURLConnection.setRequestMethod("POST"); 2.上传文件的HTTP请求中的

文件上传---普通文件fileupload.jar和url文件httpUrlConnection

文件上传---普通文件和url文件 主要用来学习使用common-fileupload.jar和java.net.httpURLConnection 普通文件: 1 //上传xls文件到临时目录 2 if (! ServletFileUpload.isMultipartContent(request)) return; 3 DiskFileItemFactory factory = new DiskFileItemFactory(); // 建立factory 4 factory.setSize

android使用HttpURLConnection实现带参数文件上传

文件上传是常见功能,然而android网上大多数的文件上传都使用httpclient,而且需要添加一个httpmine-jar,其实HttpURLConnection也可以实现文件上传,但是它在移动端有个弊端,就是不能上传大文件,所以这次说的方式,只能上传一些较小的文件. 文件上传,并且带上一些参数,这需要我们了解http请求的构造方式,也就是它的格式. HttpURLConnection需要我们自己构造请求头部,也就是我们要拼接出一个正确完整的请求. 下面来看一个典型的例子 POST /api

微信企业号上传媒体文件之服务器文件上传

微信企业号上传媒体文件之服务器文件上传 企业在使用接口时,对多媒体文件.多媒体消息的获取和调用等操作,是通过media_id来进行的. 通过接口https://qyapi.weixin.qq.com/cgi-bin/media/upload?access_token=ACCESS_TOKEN&type=TYPE,企业可以上传多媒体文件. 注意,每个多媒体文件(media_id)会在上传到微信服务器3天后自动删除,以节省服务器资源. 通常文件上传是通过html表单进行的,通过HttpURLConn

Android文件上传至服务器

项目演示及讲解 优酷  http://v.youku.com/v_show/id_XODk5NjkwOTg4.html 爱奇艺  http://www.iqiyi.com/w_19rs1v2m15.html#vfrm=8-7-0-1 土豆  http://www.tudou.com/programs/view/fv0H93IHfhM 项目下载 1.手机端选择文件上传至服务器端 http://download.csdn.net/detail/u010134178/8457679 2.手机端拍照上传

HTTP POST请求报文格式分析与Java实现文件上传

时间 2014-12-11 12:41:43  CSDN博客 原文  http://blog.csdn.net/bboyfeiyu/article/details/41863951 主题 HTTPHttpComponents 在开发中,我们使用的比较多的HTTP请求方式基本上就是GET.POST.其中GET用于从服务器获取数据,POST主要用于向服务器提交一些表单数据,例如文件上传等.而我们在使用HTTP请求时中遇到的比较麻烦的事情就是构造文件上传的HTTP报文格式,这个格式虽说也比较简单,但也

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

Android文件上传实现 分析:利用抓包工具查看文件上传发现,文件上传的请求体十分的复杂,根本难以用 HttpURLConnection.HttpClient来实现.但是用AsyncHttpClient就能很轻易的实现了,只要 在RequestParams对象里面添加一对键值对,值存储文件的路径即可上传了. AsyncHttpClient文件上传源代码:

Android开发之网络请求通信专题(二):基于HttpClient的文件上传下载

上一篇专题Android开发之网络请求通信专题(一):基于HttpURLConnection的请求通信我们讲解了如何使用httpurlconnection来实现基本的文本数据传输.一般在实际开发中我们可以用于传输xml或者json格式的数据.今天我们来讲解另外一种http网络请求的方式:httpclient,并实现文件的上传和下载. 在这里插个题外话,其实这些网络请求有很多第三方jar包可以使用,这些包都封装得很好了.如果只是想使用,我们就直接拿别人得jar包来用就好.博主这里推荐一个叫xuti

微信企业号上传媒体文件之本地文件上传

微信企业号上传媒体文件之本地文件上传 企业在使用接口时,对多媒体文件.多媒体消息的获取和调用等操作,是通过media_id来进行的. 通过接口https://qyapi.weixin.qq.com/cgi-bin/media/upload?access_token=ACCESS_TOKEN&type=TYPE,企业可以上传多媒体文件. 注意,每个多媒体文件(media_id)会在上传到微信服务器3天后自动删除,以节省服务器资源. 通常文件上传是通过html表单进行的,通过HttpURLConne