需求是模拟form表单,通过HTTP流上传文件到服务器,前面找了好多资料,很多是有jar包的,要不就是太复杂,或者过时的,不生效的。最后找了一个比较清晰的,但是这个也不完整,有错误。通过不断的了解,最终理解了实现的原理,并作出修改。
最初这个方法是通过servlet实现的,但现在都是用的springMVC 的Controller,内部代码也缺少一些配置。最终修改成下面这样。
//上传文件 private String upload(File file){ String uploadFile = file.getAbsolutePath();//读取当前文件绝对路径 String[] strs=uploadFile.split(FinalCode.IV);// 构建源文件 String newName =strs[1].substring(1);//获取相对文件路径 String fname=newName.substring(0,newName.lastIndexOf('\\')+1);//获取文件名 //上面是获取文件名,有些可以不需要 StringBuffer b = new StringBuffer();//创建Controller执行完上传返回的String String end = "\r\n";//上传模拟http String twoHyphens = "--"; String boundary = "*****"; String actionUrl = "http://127.0.0.1:8080/uploadServlet";//构建请求的Controller try { URL url = new URL(actionUrl);//构建URL HttpURLConnection con = (HttpURLConnection) url.openConnection(); con.setDoInput(true);//允许Input、Output,不使用Cache con.setDoOutput(true); con.setUseCaches(false); con.setRequestMethod("POST");//设置传送的method=POST con.setRequestProperty("Connection", "Keep-Alive");//setRequestProperty con.setRequestProperty("Charset", "UTF-8");//设置编码格式 con.setRequestProperty("Content-Type", "multipart/form-data;boundary=" + boundary);//设置是form请求 DataOutputStream ds = new DataOutputStream(con.getOutputStream());//设置DataOutputStream ds.writeBytes(twoHyphens + boundary + end);//设置结束标记 ds.writeBytes("Content-Disposition: form-data; " + "name=\"file1\";filename=\"" + newName + "\"" + end); ds.writeBytes(end);//写入结束标记 FileInputStream fStream = new FileInputStream(uploadFile);//取得文件的FileInputStream int bufferSize = 1024*500;//设置每次写入500kb byte[] buffer = new byte[bufferSize]; int length = -1; while ((length = fStream.read(buffer)) != -1) {//从文件读取数据至缓冲区 ds.write(buffer, 0, length);//将资料写入DataOutputStream中 } ds.writeBytes(end); ds.writeBytes(twoHyphens + boundary + twoHyphens + end); fStream.close();//close streams ds.flush(); InputStream is = con.getInputStream();//以流的方式取得Response返回的内容 int ch; while ((ch = is.read()) != -1) { b.append((char) ch); } ds.close();//关闭DataOutputStream } catch (Exception e) { System.out.println(("上传成功")); } return b.toString(); }
然后就是名为uploadServlet的Controller,它是在InputStream is = con.getInputStream();//以流的方式取得Response返回的内容
时会去请求这个Controller。
@RequestMapping("/uploadServlet") @ResponseBody public String uploadServlet(HttpServletRequest request) { String savePath="";//设置文件在服务器绝对路径 try { System.out.println("IP:" + request.getRemoteAddr());//监测IP DiskFileItemFactory facotry = new DiskFileItemFactory();// 1、创建工厂类:DiskFileItemFactory String tempDir = servletContext.getRealPath("/WEB-INF/temp"); facotry.setSizeThreshold(10*1024*1024);//设置内存为10M,小于10M才能上传(最初没有,造成只能上传10kb) facotry.setRepository(new File(tempDir));//设置临时文件存放目录 ServletFileUpload upload = new ServletFileUpload(facotry);// 2、创建核心解析类:ServletFileUpload upload.setHeaderEncoding("UTF-8");// 解决上传的文件名乱码 upload.setFileSizeMax(1024 * 1024 * 10);// 单个文件上传最大值是10M upload.setSizeMax(1024 * 1024 * 80);//文件上传的总大小限制80M boolean bb = upload.isMultipartContent(request);// 3、判断用户的表单提交方式是不是multipart/form-data if (!bb) return null; List<FileItem> items = upload.parseRequest(request);// 4、是:解析request对象的正文内容List<FileItem> String storePath = servletContext.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; //这里删除了获取文件夹,下面需要判断的 InputStream in = item.getInputStream();//获取当前文件的流 //这里删除了验证是否存在同类型文件,每个人的功能不一样,所以你们不需要 //这个savePath就是在Tomcat下的绝对路径了,就是storePath(这个是服务器的地址)+(前面获取的文件夹+文件名)反正你们根据需求去获取 OutputStream out = new FileOutputStream(savePath); byte b[] = new byte[1024*500]; int len = -1; while ((len = in.read(b)) != -1) { out.write(b, 0, len); } in.close(); out.close(); item.delete();//删除临时文件 } } }catch(FileUploadBase.FileSizeLimitExceededException e){ e.printStackTrace(); request.setAttribute("message", "单个文件大小不能超出10M"); }catch(FileUploadBase.SizeLimitExceededException e){ e.printStackTrace(); request.setAttribute("message", "总文件大小不能超出50M"); }catch (Exception e) { e.printStackTrace(); request.setAttribute("message", "上传失败"); } return savePath; }
我传入的是文件夹,上传上去的也是同一结构,而且我还加了一些验证,修改文件名的功能。