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
- Android笔记(三):整理——利用http上传小文件
- android利用http协议上传文件
- Android-Async-Http(1)—上传文件
- android http上传文件
- android HTTp文件上传
- 文件上传--有道笔记整理
- Android Asynchronous Http Client 开发实例——上传文件
- Android Http协议笔记(使用HttpURLConnection)文件上传+参数
- Android Http协议笔记(使用HttpURLConnection)文件上传+参数
- Android Http协议笔记(使用HttpURLConnection)文件上传+参数
- 安卓日记——利用http上传文件到服务器
- 利用HttpClient进行http文件上传
- 利用HttpClient进行http文件上传
- 利用HttpClient进行http文件上传
- 利用HttpClient进行http文件上传
- C语言 HTTP上传文件-利用libcurl库上传文件
- C语言 HTTP上传文件-利用libcurl库上传文件。
- C语言 HTTP上传文件-利用libcurl库上传文件
- freemarker添加新闻和查询新闻的小案例
- 4种mysql存储引擎比较详解
- 小狗的状态
- 交换机(链路层传输介质)
- ImgeLoader网络请求图片数字。
- Android笔记(三):整理——利用http上传小文件
- list判断既要判断list不为null,又要判断size>
- python语言开始我的博客之旅
- 面向对象程序设计上机练习八(对象数组)
- 全国第一家FPGA云主机(FAAS)正式启动售卖,被阿里云抢先了。
- 迅雷金融於菲发公开信,边缘计算、区块链是迅雷的“皇帝新衣”?
- Fedora Day1
- 早讯丨美团布局大出行领域;张旭豪:不会被美团合并
- python面试总结(二)列表去重与单例