文件上传与下载
文件上传
文件上传的几个步骤:
1 获得上传路径 如果上传的文件需要安全的存放 则应该放在WEB-INF 下面
String savePath=request.getServletContext().getRealPath("/WEB-INF/upload1");
2 创建解析工厂
DiskFileItemFactory diskFileItemFactory=new DiskFileItemFactory();
3 创建解析器
ServletFileUpload servletFileUpload=new ServletFileUpload(diskFileItemFactory);
4 判断是不是表单数据(如果是表单数据 继续进行后面操作)
ServletFileUpload.isMultipartContent(request)
5 使用ServletFileUpload解析器解析上传数据,解析结果返回的是一个List<FileItem>集合,每一个FileItem对应一个Form表单的输入项
List<FileItem> list=servletFileUpload.parseRequest(request);
6 遍历每一个FileItem
7 如果FileItem是普通表单项,则按普通表单项处理方式处理(取值),如果是文件则进行后面操作
fileItem.isFormField()
8 获取上传文件的名字(通过截取字段获得真实名字)
(1) String fileName=fileItem.getName();
此名字字符串包含包含一些系统路径,如下面这个字符串所示。
C:\Windows\Installer\{90140000-0011-0000-0000-0000000FF1CE}\graph.ico
(2) 截取字符串 获得真实名字
fileName=fileName.substring(fileName.lastIndexOf("\\")+1);
9 将fileItem写入流中(方便后面写到磁盘中)
InputStream in=fileItem.getInputStream();
10 创建输出流 并将输入流中的数据写入输出流中,并删除临时文件
FileOutputStream out = new FileOutputStream(sqlPath);
1 2 3 4 5 6 7 8 9 | byte [] bytes= new byte [ 1024 ]; int l= 0 ; while ((l=in.read(bytes))!=- 1 ){ out.write(bytes, 0 , l); } //删除处理文件上传时生成的临时文件 fileItem.delete(); msg = "文件上传成功!" ; |
文件下载的步骤:
1 获取传递过来的要下载的文件的路径和姓名参数
String filename=req.getParameter("filename");
String filepath=req.getParameter("filepath");
2 将要下载的文件放进输入流中
InputStream in = new FileInputStream(filepath);
3 设置响应头,对文件进行url编码
1 2 | filename = URLEncoder.encode(filename, "UTF-8" ); resp.setHeader( "Content-Disposition" , "attachment;filename=" +filename); |
4 创建输出流 对文件进行copy
1 2 3 4 5 6 7 8 9 10 | 拷贝 OutputStream out = resp.getOutputStream(); byte [] b = new byte [ 1024 ]; int len = 0 ; while ((len = in.read(b))!=- 1 ){ out.write(b, 0 , len); } out.flush(); out.close(); in.close() |
在本实例中 我设计了一个简单数据库file (filename 文件名,filepath 文件路径), 采用dao模式 将上传的文件的路径和文件名保存在数据库中 ,在再前台页面中奖所有的已上传的文件读取出来显示在页面上 ,在使用文件下载的方式将其下载。
具体代码如下:
《一》 文件上传
(1)前台页面
<form method="post" action="${pageContext.request.contextPath }/fileUpload1" enctype="multipart/form-data"> 上传者:<input type="text" name="username"></br> <input type="file" name="file"><br> <input type="file" name="file1"><br> <input type="submit" value="submit"> </form>
(2) web层 (上传成功后 跳转到file_uplodad/g.jsp 这个页面 注意要让文件全部操作完后再跳转,如果上传的时候有个以上文件,你在上传一个就跳转页面会程序报错)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 | protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { FileUploadServices fileUploadServices= new FileUploadServices(); /*获得上传路径*/ String savePath=request.getServletContext().getRealPath( "/WEB-INF/upload1" ); File file= new File(savePath); if (!file.exists()){ System.out.println(savePath+ "不存在,请创建" ); file.mkdir(); } String msg= "" ; //1创建解析工厂 DiskFileItemFactory diskFileItemFactory= new DiskFileItemFactory(); //2创建解析器 ServletFileUpload servletFileUpload= new ServletFileUpload(diskFileItemFactory); //中文乱码问题 servletFileUpload.setHeaderEncoding( "utf-8" ); //3判断是不是表单数据 if (!ServletFileUpload.isMultipartContent(request)){ System.out.println( "上传的不是表单数据" ); } //4、使用ServletFileUpload解析器解析上传数据,解析结果返回的是一个List<FileItem>集合,每一个FileItem对应一个Form表单的输入项 try { List<FileItem> list=servletFileUpload.parseRequest(request); for (FileItem fileItem:list){ if (fileItem.isFormField()){ String name=fileItem.getName(); String value=fileItem.getString( "utf-8" ); //解决乱码问题 System.out.println(name+ "=" +value); } else { String fileName=fileItem.getName(); //注意是getName 而不是getFileName()---file 表单中的 if (fileName!= "" ){ System.out.println(fileName+ " fileName" ); //C:\Windows\Installer\{90140000-0011-0000-0000-0000000FF1CE}\graph.ico //截取后面部分得到真实名字 \graph.ico fileName=fileName.substring(fileName.lastIndexOf( "\\" )+ 1 ); System.out.println(fileName+ "截取后面部分得到真实名字" ); //获取fileItem的输入流 InputStream in=fileItem.getInputStream(); //创建一个文件输出流 Date date= new Date(); SimpleDateFormat SimpleDateFormat= new SimpleDateFormat( "yyyy_MM_dd_HH_mm_ss" ); String da=SimpleDateFormat.format(date); String sqlPath=savePath + "\\" +da+ "_" + fileName; System.out.println(sqlPath+ " sqlPath" ); //sqlPath=sqlPath.replaceAll("\\", "/"); //判断是否上传了文件 System.out.println(sqlPath.substring(sqlPath.lastIndexOf( "_" )+ 1 )+ "dd" ); if (sqlPath.substring(sqlPath.lastIndexOf( "_" )+ 1 )!= " " ){ FileOutputStream out = new FileOutputStream(sqlPath); byte [] bytes= new byte [ 1024 ]; int l= 0 ; while ((l=in.read(bytes))!=- 1 ){ out.write(bytes, 0 , l); } //删除处理文件上传时生成的临时文件 fileItem.delete(); msg = "文件上传成功!" ; String sql= "insert into file (filepath,filename) values(?,?)" ; try { if (sqlPath.substring(sqlPath.lastIndexOf( "_" )+ 1 ).length()> 1 ){ sqlPath=sqlPath.replace( "\\" , "/" ); /*pst=(PreparedStatement) conn.prepareStatement(sql); pst.setString(1,sqlPath ); pst.setString(2,fileName ); pst.execute();*/ fileUploadServices.insert(sql, new Object[]{sqlPath,fileName}); } } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } } } } } } catch (FileUploadException e) { // TODO Auto-generated catch block e.printStackTrace(); } response.sendRedirect( "/file_uplodad/g.jsp" ); } |
(3) services层
1 2 3 4 5 6 | FileUploadDao fileUploadDao = new FileUploadDao(); public void insert(String sql,Object ...obj) { // TODO Auto-generated method stub fileUploadDao.insert(sql,obj); } |
(4)dao层
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | Connection conn= null ; ResultSet rs= null ; PreparedStatement stmt= null ; try { MyPool myPool= new MyPool( 10 ); ///自己写的简单连接池 conn=myPool.getConnection(); // 设置参数 stmt=(PreparedStatement) conn.prepareStatement(sql); ParameterMetaData parameterMetaData; parameterMetaData = stmt.getParameterMetaData(); int count =parameterMetaData.getParameterCount(); for ( int i = 1 ; i <= count; i++) { stmt.setObject(i, obj[i - 1 ]); } stmt.executeUpdate(); conn.close(); |
《二》 文件下载
文件下载dao模式和上传的差不多 ,只是从数据库中将文件名和文件路径显示出来,并作为下载时的传递参数给文件下载的servlet 这里 我就只展示文件下载的servlet
下载传递的参数:
<a href="${pageContext.request.contextPath }/download?filepath=<%=list.get(i).getFilepath()%>&filename=<%=list.get(i).getFilename() %>">下载</a>
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { //第一步:设置响应类型 resp.setContentType( "application/force-download" ); //应用程序强制下载 //第二读取文件 // String path = getServletContext().getRealPath("/up/"+name); String filename=req.getParameter( "filename" ); String filepath=req.getParameter( "filepath" ); System.out.println(filename+ " filename" ); System.out.println(filepath+ " filepath" ); InputStream in = new FileInputStream(filepath); //设置响应头,对文件进行url编码 filename = URLEncoder.encode(filename, "UTF-8" ); resp.setHeader( "Content-Disposition" , "attachment;filename=" +filename); //resp.setContentLength(in.available()); //第三步:拷贝 OutputStream out = resp.getOutputStream(); byte [] b = new byte [ 1024 ]; int len = 0 ; while ((len = in.read(b))!=- 1 ){ out.write(b, 0 , len); } out.flush(); out.close(); in.close(); |
在将上传的文件路径存入数据库之前 课改替换掉路径中的"\",故用到两个方法replace(),replaceAll(),
replace和replaceAll是JAVA中常用的替换字符的方法,它们的区别是:
1)replace的参数是char和CharSequence,即可以支持字符的替换,也支持字符串的替换(CharSequence即字符串序列的意思,说白了也就是字符串);
2)replaceAll的参数是regex,即基于规则表达式的替换,比如,可以通过replaceAll("\\d", "*")把一个字符串所有的数字字符都换成星号;
相同点:都是全部替换,即把源字符串中的某一字符或字符串全部换成指定的字符或字符串,如果只想替换第一次出现的,可以使用replaceFirst(),这个方法也是基于规则表达式的替换,但与replaceAll()不同的是,只替换第一次出现的字符串;
另外,如果replaceAll()和replaceFirst()所用的参数据不是基于规则表达式的,则与replace()替换字符串的效果是一样的,即这两者也支持字符串的操作;
还有一点注意::执行了替换操作后,源字符串的内容是没有发生改变的。
举例如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 | String src = new String( "ab43a2c43d" ); System.out.println(src.replace( "3" , "f" ));=>ab4f2c4fd. System.out.println(src.replace( '3' , 'f' ));=>ab4f2c4fd. System.out.println(src.replaceAll( "\\d" , "f" ));=>abffafcffd. System.out.println(src.replaceAll( "a" , "f" ));=>fb43fc23d. System.out.println(src.replaceFirst( "\\d," f"));=>abf32c43d System.out.println(src.replaceFirst( "4" , "h" ));=>abh32c43d. |
如何将字符串中的"\"替换成"\\":
1 2 3 4 5 | String msgIn; String msgOut; msgOut=msgIn.replaceAll( "\\\\" , "\\\\\\\\" );<br><br> |
原因:
'\'在java中是一个转义字符,所以需要用两个代表一个。例如System.out.println( "\\" ) ;只打印出一个"\"。但是'\'也是正则表达式中的转义字符(replaceAll 的参数就是正则表达式),需要用两个代表一个。所以:\\\\被java转换成\\,\\又被正则表达式转换成\。
将"\"替换成"/"
String sqlPath="C:\Windows.old\Users";
1 | sqlPath=sqlPath.replace( "\\" , "/" ); |
【推荐】2025 HarmonyOS 鸿蒙创新赛正式启动,百万大奖等你挑战
【推荐】博客园的心动:当一群程序员决定开源共建一个真诚相亲平台
【推荐】开源 Linux 服务器运维管理面板 1Panel V2 版本正式发布
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步