Android上传文件至服务器(上)

每一次都不能上首页,真悲催。。管理员让我上一次首页?
很多时候我更愿意一个人写代码,与其在垃圾代码上改改改,我更愿意直接重构。

整洁的代码简单直接。整洁的代码如同优美的散文。整洁的代码从不隐藏设计者的意图,充满了干净利落的抽象和直截了当的控制语句


(图片总是显示不好,过天换个主题。)

今天更新上传文件到服务器的内容。这两天需要将图片保存到服务器,因为一般不将图片等数据直接存储在数据库中,数据库中往往只存图片的路径,所以要将图片上传到服务器的某个文件夹中,路径保存在数据库中,这样就可以通过路径来取得图片了。

文件上传的原理

文件上传就是服务器通过request对象获取输入流(getInputStream),将浏览器上传的数据读取出来,保存到服务器端。

注意事项

  1. 请求方式必须为"POST"

  2. CONTENT_TYPE必须设置为mulitipart/form-data

  3. 如果通过网页上传文件的话需要使用组件

    <input type="file" name="file">
    

Apache-fileupload介绍

Apache-fileupload是Apache提供的方便文件上传的类,可以在commons中找到,官网网址是这个

FileUpload依赖于Commons IO,所以不要忘记包含Commons IO

顺便看一下User guide

  1. 在你确定保存文件之前,确保这是一个文件上传的请求。

    //检查是否是一个文件上传的请求
    boolean isMultipart = ServletFileUpload.isMultipartContent(request);
    
  2. 最简单的小例子

    //创建一个工厂对象
    DiskFileItemFactory factory = new DiskFileItemFactory();
    //配置临时文件存储目录
    ServletContext servletContext = this.getServletConfig().getServletContext();
    File repository = (File)servletContext.getAttribute("javax.servlet.context.tempdir");
    factory.setRepository(repository);
    //创建一个文件上传处理对象
    ServletFileUpload upload = new ServletFileUpload(factory);
    //解析请求
    List<FileItem> iterms = upload.parseRequest(request);
    
  3. 处理文件上传项

    Iterator<FileItem> iter = iterms.iterator();
    while(iter.hasNext()){
      	FileItem item = iter.next();
      	if(item.isFormField()){
          	//普通的组件
      	}else{
          	//文件上传组件,将文件保存到服务器
          	processUploadFile(item);
      	}
    }
    
  4. 官网还有限制大小、清理等功能,限于时间,我没仔细看,感兴趣的可以自己查看相关API

服务端完整实现

添加一个处理文件上传的Servlet,别忘了在Web.xml中配置,我刚开始不熟悉,想不起来配置了。多注意

public class UploadServlet extends HttpServlet {
	PrintWriter out = null;
	public void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		response.setContentType("text/html;charset=UTF-8");
		out = response.getWriter();
		//判断表单是否支持文件上传,就是查看enctype是否是:"multipart/form-data"
		boolean isMultipartContent = ServletFileUpload.isMultipartContent(request);
		if (!isMultipartContent) {
			throw new RuntimeException("表单不支持文件上传");
		}
		System.out.println("支持文件上传");
		//创建一个DiskFilefactory工厂类
		DiskFileItemFactory diskFileItemFactory = new DiskFileItemFactory();
		//配置一个临时文件存储目录
		ServletContext servletContext = this.getServletConfig().getServletContext();
		File repositoryFile = (File) servletContext.getAttribute("javax.servlet.context.tempdir");
		diskFileItemFactory.setRepository(repositoryFile);
		//创建一个新的文件上传处理类
		ServletFileUpload upload = new ServletFileUpload(diskFileItemFactory);
      	//防止中文乱码
      	 upload.setHeaderEncoding("UTF-8");
		//解析请求服务
		try {
			List<FileItem> itemsList = upload.parseRequest(request);
			//遍历表单项数据
			for (FileItem fileItem : itemsList) {
				if (fileItem.isFormField()) {
					//代表是普通表单项
				}
				else {
					//代表是文件上传表单项
					processUploadField(fileItem);
				}
			}
		} catch (FileUploadException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	private void processUploadField(FileItem fileItem) throws Exception {
		// TODO Auto-generated method stub
		//创建文件输入流
		try {
			InputStream inputStream = fileItem.getInputStream();
			String directoryRealPathString = this.getServletContext().getRealPath("/WEB-INF/upload");
			File storeDirectory = new File(directoryRealPathString);
			if (!storeDirectory.exists()) {
				storeDirectory.mkdirs();
			}
			//得到上传文件的名字
			String fileName = fileItem.getName();
			System.out.println("文件上传的名字是:"+fileName);
			if (fileName !=null) {
				fileName = fileName.substring(fileName.lastIndexOf(File.separator)+1);
			}
			//解决文件同名问题
			fileName = UUID.randomUUID()+"_"+fileName;
			//按日期进行目录打散
			String childDirectoryString = makeChildDirectory(storeDirectory,fileName);
			System.out.println("上传的文件夹是:"+childDirectoryString);
//			文件的存储路径
			String filePath = childDirectoryString+File.separator+fileName;
			//上传成功,删除临时文件
			fileItem.write(new File(storeDirectory,filePath));
			//文件的存储路径是
			System.out.println("文件的存储路径"+filePath);
//			文件存储的绝对路径
			System.out.println("绝对路径:"+storeDirectory+filePath);
			out.print("文件上传成功");
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			throw e;
		}
		catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			throw e;
		}
		
	}
	//创建文件存储目录
	private String makeChildDirectory(File storeDirectory, String fileName) {
		// TODO Auto-generated method stub
		int hashCode = fileName.hashCode();
		System.out.println("哈希吗:"+hashCode);
		//把哈希码转换为16进制的字符
		String code =Integer.toHexString(hashCode);
		System.out.println(code);
		String childDirectory = code.charAt(0)+File.separator+code.charAt(1);
		//创建制定目录
		File file = new File(storeDirectory,childDirectory);
		if (!file.exists()) {
			file.mkdirs();
		}
		return childDirectory;
	}

	public void doPost(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {

		doGet(request, response);
	}
}

### 总结

上面是服务端的实现,下一篇文章更新客户端的实现,jsp网页直接通过上传组件可以上传文件,而Android客户端可以构造一个请求,将文件上传上去。

posted on 2016-12-15 16:53  kuiblog.com  阅读(481)  评论(0编辑  收藏  举报