zoukankan      html  css  js  c++  java
  • JavaWeb:实现文件上传与下载

    JavaWeb:实现文件上传与下载

    文件上传前端处理

      本模块使用到的前端Ajax库为Axio,其地址为GitHub官网

    关于文件上传 

      上传文件就是把客户端的文件发送给服务器端。

      在常见情况(不包含文件上传)下,我们POST请求Content-Type是application/x-www-form-urlencoded,这意味着消息内容会经过URL编码,就像在GET请求时URL里的QueryString那样。txt1=hello&txt2=world。为了支持表单上传,我们第一个要设置的请求的Content-Type,即为multipart/form-data,以支持客户端向服务器发送二进制数据。 

      一个常见的请求上传格式大概是这样的:

      

    基于表单进行上传

      我们首先构建一个简易的文件上传表单,这里面有几个需要注意的地方:

    • 在form中,我们添加了enctype="multipart/form-data" 这条属性,enctype属性规定了在发送到服务器之前应该如何对表单数据进行编码
    • action="upload"> 指明了服务器接受文件的地址。 
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
        <form name="uploadForm" method="POST" enctype="multipart/form-data" action="upload">
            <table>
                <tr>
                    <td>UserName</td>
                    <td><input type="text" name="username"></td>
                </tr>
                <tr>
                    <td>upload1</td>
                    <td><input type="file" name="file"></td>
                </tr>
                <tr><td><input type="submit" name="submit" value="上传"></td></tr>
            </table>
        </form>
    </body>
    </html>

      然后,再点击上传按钮后,服务器将会接收到上传请求。  

    补充:

      在HTML5中,通过在input元素中引入多个multiple属性,使得多个文件的上传变得更加简单,下面均可使一个上传框支持多个文件上传。

    <input type="file" name="fieldName" multiple/>
    <input type="file" name="fieldName" multiple="multiple"/>
    <input type="file" name="fieldName" multiple=""/>

    基于FormData进行上传

      FormData对象用以将数据编译成键值对,以便用XMLHttpRequest来发送数据。其主要用于发送表单数据,但亦可用于发送带键数据(keyed data),而独立于表单使用。如果表单enctype属性设为multipart/form-data ,则会使用表单的submit()方法来发送数据,从而,发送数据与传统表单具有同样形式。

      简单来说就是,我们完全用JavaScript代码来拼写表单数据,如下:

    var formData = new FormData();
    
    //普通字段
    formData.append("username", "Groucho");
    formData.append("accountnum", 123456); //数字123456会被立即转换成字符串 "123456"
    
    // 文件:基于<input type=‘file’/>
    formData.append("userfile", fileInputElement.files[0]);
    
    // 文件:Blob 对象
    var content = '<a id="a"><b id="b">hey!</b></a>'; // 新文件的正文...
    var blob = new Blob([content], { type: "text/xml"});
    formData.append("webmasterfile", blob);
    

       接着,我们就可以使用axios,来上传数据,此处需要注意的是,我们需要进行请求头的设置:'Content-Type': 'multipart-/form-data'

    //构造表头
    let config = {
                headers: {
                    'Content-Type': 'multipart-/form-data'
                }
            }
    
    axios.post("//127.0.0.1:8000/web/cam", formData, config)
    	.then((response) => {…}))
    	.catch((error) =>{…});
    

       到这里,前端的处理就完成了。  

    文件上传后端处理

      表单的正文部分由多个子部分组成,如文本、数值、时间,以及文件等。Servlet3.0版本自带了上传文件的api,无需第三方jar包 。Servlet3.0将上传的文件保存在Part实例中,可以通过request对象根据上传的表单控件的name获取对应的part对象,同时也支持多个文件上传。

    @WebServlet("/up")
    @MultipartConfig  //使用MultipartConfig注解标注改servlet能够接受文件上传的请求
    public class UploadServlet extends HttpServlet {
        @Override
        protected void doPost(HttpServletRequest req, HttpServletResponse resp)
                throws ServletException, IOException {
            Part part = req.getPart("myfile");
            String disposition = part.getHeader("Content-Disposition");
            String suffix = disposition.substring(disposition.lastIndexOf("."),disposition.length()-1);
              //随机的生存一个32的字符串
            String filename = UUID.randomUUID()+suffix;
              //获取上传的文件名
            InputStream is = part.getInputStream();
            //动态获取服务器的路径
            String serverpath = req.getServletContext().getRealPath("upload");
            FileOutputStream fos = new FileOutputStream(serverpath+"/"+filename);
            byte[] bty = new byte[1024];
            int length =0;
            while((length=is.read(bty))!=-1){
                fos.write(bty,0,length);
            }
            fos.close();
            is.close();
        }
    }
    

    说明:

    • 这里需要补充一点的是,文件名的保存,Content-Disposition:form-data; name="file"; filename="test.txt" ,需要通过字符串截取得到.
    • 文件存储在服务器当前项目的根目录下的upload文件夹中,通过req.getServletContext().getRealPath()获取服务器的绝对再将上传的文件写入。 

    文件下载后端处理

      通过servlet的响应设置可以设置服务器响应文件流给客户端实现文件下载,思路是,客户端发送请求给服务端告诉服务端需要下载的文件,服务端读取该文件,转换为输入流,在通过outputstream响应给客户端,不过需要设置response的头信息,下面是完整代码

    public class DownServlet extends HttpServlet {
        public void doGet(HttpServletRequest request, HttpServletResponse response)
                throws ServletException, IOException {
            String file = request.getParameter("file"); //客户端传递的需要下载的文件名
            String path = request.getServletContext().getRealPath("")+"/"+file; //默认认为文件在当前项目的根目录
            FileInputStream fis = new FileInputStream(path);
            response.setCharacterEncoding("utf-8");
            response.setHeader("Content-Disposition", "attachment; filename="+file);
            ServletOutputStream out = response.getOutputStream();
            byte[] bt = new byte[1024];
            int length = 0;
            while((length=fis.read(bt))!=-1){
                out.write(bt,0,length);
            }
            out.close();
        }
    }
    

      

  • 相关阅读:
    【BZOJ3028】食物(生成函数基础题)
    【BZOJ2438】[中山市选2011] 杀人游戏(Tarjan)
    【BZOJ4833】[Lydsy1704月赛] 最小公倍佩尔数(神仙数学题)
    【BZOJ2109】【BZOJ2535】[NOI2010] 航空管制(拓扑反向建图)
    【BZOJ2679】[USACO2012 Open] Balanced Cow Subsets(Meet in Middle)
    【BZOJ3091】城市旅行(再次重拾LCT)
    sass与compass实战
    【Sass初级】开始使用Sass和Compass
    nodejs、sass、backbone等api地址
    解读2015之前端篇:工业时代 野蛮发展(转)
  • 原文地址:https://www.cnblogs.com/MrSaver/p/6028503.html
Copyright © 2011-2022 走看看