Tomcat下文件下载与上传的简单实现

您所在的位置:网站首页 tomcat下载文件不能超过20M Tomcat下文件下载与上传的简单实现

Tomcat下文件下载与上传的简单实现

2024-07-14 20:45| 来源: 网络整理| 查看: 265

实现下载 修改server.xml修改web.xml 实现上传 实现客户端的上传 post请求代码实现 实现服务端的处理 小结

实现下载

实现下载需要 - 修改Tomcat中的server.xml - 修改web.xml

修改server.xml

在 中加入(一般在文件末尾可以找到)

其中docBase项是本地目录,path项是访问目录

修改web.xml default org.apache.catalina.servlets.DefaultServlet debug 0 listings true 1

其中listings下确保值是true

这时在C://Download下存放文件,并打开相应的地址,就能看见文件目录了

实现上传

实现上传也是分两步

实现客户端的上传实现服务端的处理 实现客户端的上传 post请求

我们都知道http常用的请求方式有get、post等,其中我们实现文件上传,就是模拟表单采用post方式上传文件

首先来看一下post报文的格式,以上传一张图片为例

POST/logsys/home/uploadIspeedLog!doDefault.html HTTP/1.1 Accept: text/plain, */* Accept-Language: zh-cn Host: 192.168.24.56 Content-Type:multipart/form-data;boundary=【这里随意设置】 User-Agent: WinHttpClient Content-Length: 3693 Connection: Keep-Alive

以上部分是请求的参数,不需要我们完全实现,通过方法传参的方式自动构建

--【这里随意设置】 Content-Disposition: form-data;name="file1";filename="C://E//a.png" Content-Type:application/octet-stream --【这里随意设置】--

这一部分是报文的内容,需要我们通过字符串或者字节流自行拼接,并且格式不能出错

注意,三处【这里随意设置】的部分必须完全相同

代码实现 public static void uploadFile(String fileName) { try { // 换行符 final String newLine = "\r\n"; //数据分隔线 final String BOUNDARY = "【这里随意设置】";//可以随意设置,一般是用 ---------------加一堆随机字符 //文件结束标识 final String boundaryPrefix = "--"; // 服务器的域名 URL url = new URL("http://localhost:8070/secondary/HandleFile"); HttpURLConnection conn = (HttpURLConnection) url.openConnection(); // 设置为POST情 conn.setRequestMethod("POST"); // 发送POST请求必须设置如下两行 conn.setDoOutput(true); //conn.setDoInput(true);/不必加,默认为true //conn.setUseCaches(false);//用于设置缓存,默认为true,不改也没有影响(至少在传输单个文件这里没有) // 设置请求头参数 //关于keep-alive的说明:https://www.kafan.cn/edu/5110681.html //conn.setRequestProperty("connection", "Keep-Alive");//现在的默认设置一般即为keep-Alive,因此此项为强调用,可以不加 //conn.setRequestProperty("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows Nt 5.1; SV1)");//用于模拟浏览器,非必须 //用于表示上传形式,必须 conn.setRequestProperty("Content-Type", "multipart/form-data; boundary=" + BOUNDARY); //这里是Charset,网上大多都是Charsert???我的天,笑哭。不过好像没什么影响...不知道哪位大佬解释一下 conn.setRequestProperty("Charset", "UTF-8"); //获取conn的输出流用于向服务器输出信息 OutputStream out = new DataOutputStream(conn.getOutputStream()); //构造文件的结构 //写参数头 StringBuilder sb = new StringBuilder(); sb.append(boundaryPrefix)//表示报文开始 .append(BOUNDARY)//添加文件分界线 .append(newLine);//换行,换行方式必须严格约束 //固定格式,其中name的参数名可以随意修改,只需要在后台有相应的识别就可以,filename填你想要被后台识别的文件名,可以包含路径 sb.append("Content-Disposition: form-data;name=\"file\";") .append("filename=\"").append(fileName) .append("\"") .append(newLine); sb.append("Content-Type:application/octet-stream"); //换行,为必须格式 sb.append(newLine); sb.append(newLine); //将参数头的数据写入到输出流中 out.write(sb.toString().getBytes()); System.out.print(sb); //写文件数据(通过数据输入流) File file = new File(fileName); DataInputStream in = new DataInputStream(new FileInputStream( file)); byte[] bufferOut = new byte[1024]; int bytes = 0; //每次读1KB数据,并且将文件数据写入到输出流中 while ((bytes = in.read(bufferOut)) != -1) { out.write(bufferOut, 0, bytes); } in.close(); //写参数尾 out.write(newLine.getBytes()); System.out.print(new String(newLine.getBytes())); // 定义最后数据分隔线,即--加上BOUNDARY再加上--。 sb = new StringBuilder(); sb.append(newLine) .append(boundaryPrefix) .append(BOUNDARY) .append(boundaryPrefix) .append(newLine); // 写上结尾标识 out.write(sb.toString().getBytes()); System.out.println(sb); //输出结束,关闭输出流 out.flush(); out.close(); //定义BufferedReader输入流来读取URL的响应 ,注意必须接受来自服务器的返回,否则服务器不会对发送的post请求做处理!!这里坑了我好久 BufferedReader reader = new BufferedReader(new InputStreamReader( conn.getInputStream())); String line = null; while ((line = reader.readLine()) != null) { System.out.println(line); } } catch (Exception e) { System.out.println("发送POST请求出现异常!" + e); e.printStackTrace(); } }

注释很清楚,结合post请求的格式理解一下,就不一一解释了

实现服务端的处理

上述的代码会形成一个post请求到服务器,于是相应的接口的dopost()方法就会相应

dopost()中做了什么呢?

获取报文中的文件信息处理文件信息,包括识别文件名,识别文件类型(由用户定义,而不是文件后缀)存储到本地(服务器端硬盘)

代码如下:

import org.apache.commons.fileupload.FileItem; import org.apache.commons.fileupload.FileUploadException; import org.apache.commons.fileupload.disk.DiskFileItemFactory; import org.apache.commons.fileupload.servlet.ServletFileUpload; //注意导的包 /** * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response) */ public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.setCharacterEncoding("UTF-8"); request.setCharacterEncoding("UTF-8"); response.setContentType("text/html"); PrintWriter out = response.getWriter(); //输出到客户端浏览器 DiskFileItemFactory factory = new DiskFileItemFactory(); ServletFileUpload sup = new ServletFileUpload(factory);//这里要将factory传入,否则会报NullPointerException: No FileItemFactory has been set. try{ List list = sup.parseRequest(request); for(FileItem fileItem:list){ System.out.println(fileItem.getFieldName()+"--"+fileItem.getName()); if(!fileItem.isFormField()){ if("file".equals(fileItem.getFieldName())){ //获取远程文件名 String remoteFilename = new String(fileItem.getName().getBytes(),"UTF-8"); File remoteFile = new File(remoteFilename); //设置服务器端存放文件的位置 File locate = new File("C://E//download/",remoteFile.getName()); // locate.getParentFile().mkdirs();//用于确保文件目录存在,如果为单级目录可以去掉 locate.createNewFile(); //创建新文件 InputStream ins = fileItem.getInputStream(); //FileItem的内容 OutputStream ous = new FileOutputStream(locate); //输出 try{ byte[] buffer = new byte[1024]; //缓冲字节 int len = 0; while((len = ins.read(buffer))>-1) ous.write(buffer, 0, len); }finally{ ous.close(); ins.close(); } } } } }catch (FileUploadException e){} out.print("everything is ok"); out.flush(); out.close(); }

同样注释很清楚,不再解释了

小结

将上述过程理解清楚后,再结合post报文的格式,那么是否就可以处理多个文件同时上传了呢?如果对客户端的流做出一些大小限制,是不是就可以限制上传大小了?…一个小demo,帮助理解一下基础的实现。



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3