精华内容
参与话题
问答
  • JavaWeb实现文件上传下载

    千次阅读 2018-07-26 17:22:25
    1.创建web项目 2. 上传文件页面 必须要设置input输入项的name属性,否则浏览器将不会发送上传文件...并使用MIME协议对上传文件进行描述,以方便接收方对上传数据进行解析和处理。 <%@ page conte...

    1.创建web项目

    2. 上传文件页面

    必须要设置input输入项的name属性,否则浏览器将不会发送上传文件的数据

    必须把form的enctype属值设为multipart/form-data.设置该值后,浏览器在上传文件时,将把文件数据附带在http请求消息体中,

    并使用MIME协议对上传的文件进行描述,以方便接收方对上传数据进行解析和处理。

    <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    <html>
    <head>
        <title>Title</title>
    </head>
    <body>
    <!-- 实现文件的上传 -->
    <!-- 1.要上传文件 表单提交请求的方式必须为post请求 -->
    <!-- 2.要上传文件 需要设置form表单的enctype
    	application/x-www-form-urlencoded是form表单enctype的默认值
    	需要将enctype的值设置为 multipart/form-data
    -->
    <form action="/UploadServlet" enctype="multipart/form-data" method="post">
        上传用户:<input type="text" name="username"><br/>
        上传文件:<input type="file" name="file1"><br/>
        上传文件:<input type="file" name="file2"><br/>
        <input type="submit" value="提交">
    </form>
    </body>
    </html>

    3.

    使用Commons-fileupload组件实现文件上传,需要导入该组件相应的支撑jar包:Commons-fileupload和commons-io。

    将jar包放置lib文件夹下后,还需配置他的位置信息

    4.上传文件Servlet

    DiskFileItemFactory 是创建 FileItem 对象的工厂

    ServletFileUpload 负责处理上传的文件数据,并将表单中每个输入项封装成一个 FileItem 对象中

    FileItem类负责处理表单提交的字段

    上传文件步骤:

     

    1. 创建DiskFileItemFactory对象,设置缓冲区大小和临时文件目录;
    2. 使用DiskFileItemFactory 对象创建ServletFileUpload对象,并设置上传文件的大小限制;
    3. 调用ServletFileUpload.parseRequest方法解析request对象,得到一个保存了所有上传内容的List对象;
    4. 对list进行迭代,每迭代一个FileItem对象,调用其isFormField方法判断是否是上传文件;如果是上传文件,则写出上传数据。
    package com.study;
    
    import java.io.File;
    import java.io.IOException;
    import java.util.Date;
    import java.util.List;
    
    import javax.servlet.ServletException;
    import javax.servlet.annotation.WebServlet;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    
    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;
    
    @WebServlet("/UploadServlet")
    public class UploadServlet extends HttpServlet {
        private static final long serialVersionUID = 1L;
        public UploadServlet() {
            super();
        }
        protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            doPost(request,response);
        }
        protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            //获得一个文件上传的工厂类
            DiskFileItemFactory dfif = new DiskFileItemFactory();//DiskFileItemFactory 是创建 FileItem 对象的工厂
            //设置文件上传临时存储的大小8M
            dfif.setSizeThreshold(1024*1024*8);
            //指定临时文件目录,默认值为当前用户的系统临时文件目录,可通过System.getProperty(“java.io.tmpdir”)打印查看;
            dfif.setRepository(new File("java.io.tmpdir"));
            System.out.println(System.getProperty("java.io.tmpdir"));
            //使用servlet来处理文件上传
            ServletFileUpload upload = new ServletFileUpload(dfif);
            //设置文件上传的大小
            upload.setSizeMax(1024*1024*50);
            //获得当前服务器的路径
            String uploadPath = this.getServletContext().getRealPath("");
            System.out.println("当前服务器路径---->"+uploadPath);
            uploadPath = uploadPath+"..\\"+"upload";
            File uploadDir = new File(uploadPath);
            if(!uploadDir.exists()){
                uploadDir.mkdir();
            }
            try {
                List<FileItem> formItem = upload.parseRequest(request);
                if(formItem != null && formItem.size() >0){
                    //循环遍历要上传的文件
                    for(FileItem item : formItem){
                        if(!item.isFormField()){
    			//获得要上传的文件的名字
                            String fileName = new File(item.getName()).getName();
                            //fileName = new Date().getTime()+(int)(Math.random()*100)+fileName;
    
                            //目的文件
                            String filePath = uploadPath+"\\"+fileName;
                            File storeFile = new File(filePath);
                            item.write(storeFile);
    
                            System.out.println(fileName);
                            System.out.println(filePath);
                            //request.setAttribute("fileName", fileName);
                        }
                    }
                }
            } catch (FileUploadException e) {
                e.printStackTrace();
                request.setAttribute("message", "文件上传失败:"+e.getMessage());
                request.getRequestDispatcher("error.jsp").forward(request, response);
            } catch (Exception e) {
                e.printStackTrace();
            }
            request.getRequestDispatcher("upload.jsp").forward(request, response);
        }
    
    }
    
    

     5.下载文件页面

    <body>
    <!-- 实现文件下载 需要跳转至servlet 用流来处理 -->
    <a href="/DownLoadServlet"><h3>下载</h3></a>
    </body>

    6.下载文件Servlet

    服务器希望浏览器不直接处理相应的实体内容,而是由用户选择将相应的实体内容保存到一个文件

    这需要设置 Content-Disposition 响应头。

    先使用文件输入流 将文件读到内存中 再使用输出流 将文件输出给用户

    package com.study;
    
    import java.io.File;
    import java.io.FileInputStream;
    import java.io.IOException;
    
    import javax.servlet.ServletException;
    import javax.servlet.ServletOutputStream;
    import javax.servlet.annotation.WebServlet;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    
    @WebServlet("/DownLoadServlet")
    public class DownLoadServlet extends HttpServlet {
    	private static final long serialVersionUID = 1L;
    
        public DownLoadServlet() {
            super();
        }
    
    	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    		doPost(request,response);
    	}
    
    	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    		//实现文件下载 设置响应头
    		String fileName = this.getServletContext().getRealPath("")+"../"+"upload/"+"zly.jpg";
    		response.setHeader("Content-Disposition", "attachment;filename="+fileName);
    		System .out.print("fileName"+fileName);
    		//先使用文件输入流 将文件读到内存中 再使用输出流 将文件输出给用户
    		File file = new File(fileName);
    		FileInputStream fileIn = new FileInputStream(file);
    		//准备一个缓冲区
    		byte[] b = new byte[(int)file.length()];
    		//将文件读入缓冲区中
    		fileIn.read(b);
    		//获得响应的输出流
    		ServletOutputStream sout = response.getOutputStream();
    //调用response.getOutputStream()方法返回 ServeltOutputStream 对象来向客户端写入文件内容。
    		sout.write(b);
    		sout.close();
    	}
    }
    

     

    展开全文
  • 我这是使用springboot写的不用导额外的包,如果ssm做的话...上传文件 在input框里加上multiple属性,就可以一个input框一下上传多个文件 这是上传按钮的事件FormData这一行就这么写就行,参数换成form表单的id,直...

    我这是使用springboot写的不用导额外的包,如果ssm做的话需要导包可以查看下面这个

    https://blog.csdn.net/kxj19980524/article/details/83536366

    上传文件

    在input框里加上multiple属性,就可以一个input框一下上传多个文件

    这是上传按钮的事件 FormData这一行就这么写就行,参数换成form表单的id,直接就把form表单里所有参数传到后台了,包括上传的文件.

       //点击上传
        $("#businessLicenseBtn").click(function () {  //加一个单击事件按钮
            var formd = new FormData($("#userCompleteForm")[0]);    //$("#userCompleteForm")[0]:把form表单对象转换为js对象
            $.ajax({
                url:"${pageContext.request.contextPath}/WitkeyDemandScheme/uploadSchemes",//跳转到后台路径
                type:"post",
                data:formd,
                dataType:"json",
                processData:false,    //用form表单的enctype对象   这两个属性加上就行了
                contentType:false,      //默认为true,上传数据转为对象,为false  不转为对象
                success:function (data) {
                    var div1 = $("#div1");
                    $(data).each(function (a,b) {
                        div1.append(b+"<input type='button' onclick='deleteScheme("+b+")' value='删除'/><br/>")
                    })
                },
                error:function(){
                    alert("上传失败!")
                }
            })
        })

     这是后台上传文件的代码,跟上传单个文件一样,只不过,sql语句使用foreach变量就好了,这里面逻辑就是把文件名字多加了点避免上传上去的文件名重复.

        //批量上传文件
        @RequestMapping("/uploadSchemes")
        @ResponseBody
        public List<String> uploadSchemes(MultipartFile[] files,Integer demandId,Integer userId){
            List<String> list = new ArrayList<>();
            String realPath = "E:\\idea\\project\\springboot\\witkey\\src\\main\\webapp\\uploads\\files";
           for(int i=0;i<files.length;i++){
               long size = files[i].getSize();
               if(size>1000000){
                   list.add("该文件太大,无法上传");
                   return list;
               }
               //获取文件名称
               String filename = files[i].getOriginalFilename();
               filename = saveNewFileName(filename,demandId,userId);
               list.add(filename);
               File f = new File(realPath+File.separator+filename);
               try {
                   files[i].transferTo(f);
               } catch (IOException e) {
                   e.printStackTrace();
               }
           }
            witkeyDemandSchemeService.insertDemandSchemes(demandId,userId,list);
            return list;
        }
    
        private String saveNewFileName(String filename, Integer demandId, Integer userId) {
            int index = filename.indexOf(".");
            return filename.substring(0,index)+"_"+demandId+"_"+userId+filename.substring(index);
        }

    文件下载

    前台就是写了个单击事件,把文件名称传到后台了,这个跳转路径别用ajax方式跳转.

     

    这是后台的controller方法,接收方式必须是restful风格接收参数不然会下载不正确

    import org.apache.tomcat.util.http.fileupload.IOUtils;
     
       @RequestMapping("/downloadScheme/{filename:.+}")
        public void downloadScheme(@PathVariable String filename, HttpServletResponse response){
            //获取下载路径
            String realPath = "E:\\idea\\project\\springboot\\witkey\\src\\main\\webapp\\uploads\\files";
    
            File file = new File(realPath,filename);
            //读取下载的文件
            try(
                    InputStream in = new FileInputStream(file);
                    OutputStream out = response.getOutputStream();
                    ){
                response.setContentType("application/x-download");
                filename= URLEncoder.encode(filename,"UTF-8");
                response.addHeader("ContentDisposition","attachment;filename="+filename);
                IOUtils.copy(in,out);
                out.flush();
            }catch (Exception e){
                e.printStackTrace();
            }
        }

    实现效果

     

    断点续传版文件下载

        //实现文件下载功能
        @RequestMapping("/downloadScheme/{filename:.+}")
        public void downloadFile(@PathVariable String filename, HttpServletResponse response, HttpServletRequest request){
            File dir = new File("/var/www/tena-service/log");//获取文件路劲
    
            File downloadFile = new File(dir, filename);//在指定目录下查找文件
    
            try {
                downloadFileRanges(downloadFile, request,  response,filename);
            } catch(ClientAbortException e){
                System.out.println("连接被终止");
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    
        private void downloadFileRanges(File downloadFile, HttpServletRequest request, HttpServletResponse response,String filename) throws IOException {
            // 要下载的文件大小
            long fileLength = downloadFile.length();
            // 已下载的文件大小
            long pastLength = 0;
            // 是否快车下载,否则为迅雷或其他
            boolean isFlashGet = true;
            // 用于记录需要下载的结束字节数(迅雷或其他下载)
            long lenEnd = 0;
            // 用于记录客户端要求下载的数据范围字串
            String rangeBytes = request.getHeader("Range");
            //用于随机读取写入文件
            RandomAccessFile raf = null;
            OutputStream os = null;
            OutputStream outPut = null;
            byte b[] = new byte[1024];
            // 如果客户端下载请求中包含了范围
            if (null != rangeBytes)
            {
                // 返回码 206
                response.setStatus(HttpServletResponse.SC_PARTIAL_CONTENT);
                rangeBytes = request.getHeader("Range").replaceAll("bytes=", "");
                // 判断 Range 字串模式
                if (rangeBytes.indexOf('-') == rangeBytes.length() - 1)
                {
                    // 无结束字节数,为快车
                    isFlashGet = true;
                    rangeBytes = rangeBytes.substring(0, rangeBytes.indexOf('-'));
                    pastLength = Long.parseLong(rangeBytes.trim());
                }
                else
                {
                    // 迅雷下载
                    isFlashGet = false;
                    String startBytes = rangeBytes.substring(0,
                            rangeBytes.indexOf('-'));
                    String endBytes = rangeBytes.substring(
                            rangeBytes.indexOf('-') + 1, rangeBytes.length());
                    // 已下载文件段
                    pastLength = Long.parseLong(startBytes.trim());
                    // 还需下载的文件字节数(从已下载文件段开始)
                    lenEnd = Long.parseLong(endBytes);
                }
            }
            // 通知客户端允许断点续传,响应格式为:Accept-Ranges: bytes
            response.setHeader("Accept-Ranges", "bytes");
            // response.reset();
            // 如果为第一次下载,则状态默认为 200,响应格式为: HTTP/1.1 200 ok
            if (0 != pastLength)
            {
                // 内容范围字串
                String contentRange = "";
                // 响应格式
                // Content-Range: bytes [文件块的开始字节]-[文件的总大小 - 1]||[文件的总大小]
                if (isFlashGet)
                {
                    contentRange = new StringBuffer("bytes")
                            .append(new Long(pastLength).toString()).append("-")
                            .append(new Long(fileLength - 1).toString())
                            .append("/").append(new Long(fileLength).toString())
                            .toString();
                }
                else
                {
                    contentRange = new StringBuffer(rangeBytes).append("/")
                            .append(new Long(fileLength).toString()).toString();
                }
                response.setHeader("Content-Range", contentRange);
            }
            String fileName = getDownloadChineseFileName(filename);
            response.setHeader("Content-Disposition",
                    "attachment;filename=" + fileName + "");
            // 响应的格式是:
            response.setContentType("application/octet-stream");
            response.addHeader("Content-Length", String.valueOf(fileLength));
            try
            {
                os = response.getOutputStream();
                outPut = new BufferedOutputStream(os);
                raf = new RandomAccessFile(downloadFile, "r");
                // 跳过已下载字节
                raf.seek(pastLength);
                if (isFlashGet)
                {
                    // 快车等
                    int n = 0;
                    while ((n = raf.read(b, 0, 1024)) != -1)
                    {
                        outPut.write(b, 0, n);
                    }
                }
                else
                {
                    // 迅雷等
                    while (raf.getFilePointer() < lenEnd)
                    {
                        outPut.write(raf.read());
                    }
                }
                outPut.flush();
            }
            catch (IOException e)
            {
                /**
                 * 在写数据的时候 对于 ClientAbortException 之类的异常
                 * 是因为客户端取消了下载,而服务器端继续向浏览器写入数据时, 抛出这个异常,这个是正常的。 尤其是对于迅雷这种吸血的客户端软件。
                 * 明明已经有一个线程在读取 bytes=1275856879-1275877358,
                 * 如果短时间内没有读取完毕,迅雷会再启第二个、第三个。。。线程来读取相同的字节段, 直到有一个线程读取完毕,迅雷会 KILL
                 * 掉其他正在下载同一字节段的线程, 强行中止字节读出,造成服务器抛 ClientAbortException。
                 * 所以,我们忽略这种异常
                 */
            }
            finally
            {
                if(outPut != null)
                {
                    outPut.close();
                }
                if(raf != null)
                {
                    raf.close();
                }
            }
        }
    
    
    
        private String getDownloadChineseFileName(String paramName)
        {
            String downloadChineseFileName = "";
            try
            {
                downloadChineseFileName = new String(paramName.getBytes("GBK"),
                        "ISO8859-1");
            }
            catch (UnsupportedEncodingException e)
            {
                e.printStackTrace();
            }
            return downloadChineseFileName;
        }

     

    展开全文
  • java web文件上传——FileUpload

    万次阅读 多人点赞 2018-08-31 17:03:30
    文件上传分析 1.普通表单提交默认enctype="application/x-www-form-urlencoded";但是当表单中存在文件类型时,需要设置enctype="multipart/form-data",它不对字符进行编码,用于发送二进制的...

    文件上传分析

    1.普通表单提交默认enctype="application/x-www-form-urlencoded";但是当表单中存在文件类型时,需要设置enctype="multipart/form-data",它不对字符进行编码,用于发送二进制的文件(即所有文件类型,如视频、图片、音乐、文档都可以用此类型entype);还有一种enctype="text/plain"用于发送纯文本内容。

    2.表单请求方式必须为post。

    3.接收时不能再用request.getParameter(),而是request.getInputStream()解析二进制流,得到ServletInputStream对象。

     

    接下来我们来看看上传一个t文件接收到的二进制流转化为字符串是什么:

    (1)表单提交页面:

    <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    <html>
    
    <head>
        <title>练习</title>
    </head>
    <body>
    <form action="/UploadServlet" enctype="multipart/form-data" method="post">
        <input type="text" name="username">
        <input type="password" name="pwd">
        <input type="file" name="pic">
        <input type="submit">
    </form>
    
    </body>
    </html>

    (2)接收文件流UploadServlet:

    
    import javax.servlet.ServletException;
    import javax.servlet.annotation.WebServlet;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import java.io.IOException;
    import java.io.InputStream;
    
    @WebServlet("/UploadServlet")
    public class UploadServlet extends HttpServlet {
        protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            //获取复杂表单的输入流
            InputStream in=request.getInputStream();
    
            //输入流转化为字符串
            byte[] b=new byte[1024];
            in.read(b);
            System.out.println(new String(b));
        }
    
        protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            doPost(request,response);
        }
    }
    

    运行项目:

    (1)表单填写:

    test.txt中的内容是:

    hello world
    好好学习,天天向上
    

    (2)点击提交,运行结果:

    ------WebKitFormBoundaryzRSPAU9UKnMzdAUZ
    Content-Disposition: form-data; name="username"
    
    hello 灏忛奔
    ------WebKitFormBoundaryzRSPAU9UKnMzdAUZ
    Content-Disposition: form-data; name="pwd"
    
    12345
    ------WebKitFormBoundaryzRSPAU9UKnMzdAUZ
    Content-Disposition: form-data; name="pic"; filename="test.txt"
    Content-Type: text/plain
    
    锘縣ello world
    濂藉ソ瀛︿範锛屽ぉ澶╁悜涓?
    
    ------WebKitFormBoundaryzRSPAU9UKnMzdAUZ--

    分析:------WebKitFormBoundaryzRSPAU9UKnMzdAUZ--是分隔符,用于分隔表单的每一个字段。运行结果中有中文乱码后续会处理。将二进制流转化为字符串除了上面用的read()方法,还可以用org.apache.commons.io.IOUtils.toString(in),不过要导入jar包。

     

    FileUpload文件上传

    1.FileUpload分析

    fileUpload是apache的commons组件提供的上传组件,它最主要的工作就是帮我们解析request.getInpustream()。可以参考在线API文档:http://tool.oschina.net/apidocs/apidoc?api=commons-fileupload

    使用fileUpload组件首先需要引入两个jar包:

    • commons-fileUpload.jar
    • commons-io.jar

    fileUpload的核心类有DiskFileItemFactory、ServletFileUpload、FileItem。

    使用fileUpload固定步骤:

    1. 创建工厂类:DiskFileItemFactory factory=new DiskFileItemFactory();
    2. 创建解析器:ServletFileUpload upload=new ServletFileUpload(factory);
    3. 使用解析器解析request对象:List<FileItem> list=upload.parseRequest(request);

    一个FileItem对象对应一个表单项。FileItem类有如下方法:

    • String getFieldName():获取表单项的name的属性值。
    • String getName():获取文件字段的文件名。如果是普通字段,则返回null
    • String getString():获取字段的内容。如果是普通字段,则是它的value值;如果是文件字段,则是文件内容。
    • String getContentType():获取上传的文件类型,例如text/plain、image。如果是普通字段,则返回null。
    • long getSize():获取字段内容的大小,单位是字节。
    • boolean isFormField():判断是否是普通表单字段,若是,返回true,否则返回false。
    • InputStream getInputStream():获得文件内容的输入流。如果是普通字段,则返回value值的输入流。

     

    表单提交页面同上,修改UploadServlet的代码如下:

    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;
    import sun.misc.IOUtils;
    
    import javax.servlet.ServletException;
    import javax.servlet.annotation.WebServlet;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import java.io.IOException;
    import java.io.InputStream;
    import java.util.List;
    
    @WebServlet("/UploadServlet")
    public class UploadServlet extends HttpServlet {
        protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            DiskFileItemFactory factory=new DiskFileItemFactory();
            ServletFileUpload upload=new ServletFileUpload(factory);
            try {
                List<FileItem> list=upload.parseRequest(request);
                for (FileItem fileItem:list){
                    System.out.println("fieldName:"+fileItem.getFieldName());
                    System.out.println("name:"+fileItem.getName());
                    System.out.println("string:"+fileItem.getString());
                    System.out.println("contentType:"+fileItem.getContentType());
                    System.out.println("size:"+fileItem.getSize()+"byte");
                    System.out.println("isFieldForm:"+fileItem.isFormField());
                    System.out.println("inputStream:"+ org.apache.commons.io.IOUtils.toString(fileItem.getInputStream()));
                    System.out.println("*************");
                }
            } catch (FileUploadException e) {
                e.printStackTrace();
            }
        }
    
        protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            doPost(request,response);
        }
    }
    

    运行结果:

    (1)填写表单:

    (2)test.txt同上,点击提交结果:

    fieldName:username
    name:null
    string:hello ?°?é±?
    contentType:null
    size:12byte
    isFieldForm:true
    inputStream:hello 灏忛奔
    *************
    fieldName:pwd
    name:null
    string:12345
    contentType:null
    size:5byte
    isFieldForm:true
    inputStream:12345
    *************
    fieldName:pic
    name:test.txt
    string:???hello world
    ???????????? ?¤??¤???????
    
    contentType:text/plain
    size:43byte
    isFieldForm:false
    inputStream:锘縣ello world
    濂藉ソ瀛︿範 澶╁ぉ鍚戜笂
    
    *************

    2.FileUpload实现文件上传

    使用fileUpload组件实现文件上传除了上面的那些方法之外还要注意的:

    1. 文件名中文乱码处理:servletFileUpload.setHeaderEncoding("utf-8") 或 request.setCharacterEncoding("utf-8");
    2. 表单普通字段中文乱码处理:new String(str.getBytes("iso-8859-1","utf-8"));
    3. 设置内存缓冲区的大小,默认为10KB:diskFileItemFactory.setSizeThreshold(1024*1024);
    4. 指定临时文件目录,如果单个文件的大小超过内存缓冲区,该文件将会临时缓存在此目录下:diskFileItemFactory.setRepository(file);
    5. 设置单个文件大小限制,如果有某个文件超过此大小,将抛出FileUploadBase.FileSizeLimitExceededException:servletFileUpload.setFileSizeMax(1024*1024*10);
    6. 设置所有文件,也就是请求大小限制,如果文件总和超过此大小,将抛出FileUploadBase.SizeLimitExceededException:servletFileUpload.setSizeMax(1024*1024*20);
    7. 利用UUID生成伪随机字符串作为文件名避免重复:UUID.randomUUID().toString();
    8. 将文件写到硬盘上。写完之后,系统会自动将放在临时文件目录的该文件删除:fileItem.write(new File(path,fileName));

    注:如果没有指定临时文件目录,默认采用系统默认的临时文件路径,可以通过System.getProperty("java.io.tmpdir")获取,Tomcat系统默认临时目录为“<tomcat安装目录>/temp/”。

    Apache文件上传组件在解析上传数据中的每个字段内容时,需要临时保存解析出的数据,以便在后面进行数据的进一步处理(保存在磁盘特定位置或插入数据库)。因为Java虚拟机默认可以使用的内存空间是有限的,超出限制时将会抛出“java.lang.OutOfMemoryError”错误。如果上传的文件很大,例如800M的文件,在内存中将无法临时保存该文件内容,Apache文件上传组件转而采用临时文件来保存这些数据;但如果上传的文件很小,例如600个字节的文件,显然将其直接保存在内存中性能会更加好些。

     

    表单提交页面不变,UploadServlet代码如下:

    
    
    import org.apache.commons.fileupload.FileItem;
    import org.apache.commons.fileupload.FileUploadBase;
    import org.apache.commons.fileupload.FileUploadException;
    import org.apache.commons.fileupload.disk.DiskFileItemFactory;
    import org.apache.commons.fileupload.servlet.ServletFileUpload;
    import sun.misc.IOUtils;
    
    import javax.servlet.ServletException;
    import javax.servlet.annotation.WebServlet;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import java.io.File;
    import java.io.IOException;
    import java.io.InputStream;
    import java.util.List;
    import java.util.UUID;
    
    @WebServlet("/UploadServlet")
    public class UploadServlet extends HttpServlet {
        protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            DiskFileItemFactory factory=new DiskFileItemFactory();
            ServletFileUpload upload=new ServletFileUpload(factory);
    
            request.setCharacterEncoding("utf-8");
            //文件名中文乱码处理也可以如此写
    //        upload.setHeaderEncoding("utf-8");
    
            //设置缓冲区大小与临时文件目录
            factory.setSizeThreshold(1024*1024*10);
            File uploadTemp=new File("e:\\uploadTemp");
            uploadTemp.mkdirs();
            factory.setRepository(uploadTemp);
    
            //设置单个文件大小限制
            upload.setFileSizeMax(1024*1024*10);
            //设置所有文件总和大小限制
            upload.setSizeMax(1024*1024*30);
    
            try {
                List<FileItem> list=upload.parseRequest(request);
                System.out.println(list);
                for (FileItem fileItem:list){
                    if (!fileItem.isFormField()&&fileItem.getName()!=null&&!"".equals(fileItem.getName())){
                        String filName=fileItem.getName();
                        //利用UUID生成伪随机字符串,作为文件名避免重复
                        String uuid= UUID.randomUUID().toString();
                        //获取文件后缀名
                        String suffix=filName.substring(filName.lastIndexOf("."));
    
                        //获取文件上传目录路径,在项目部署路径下的upload目录里。若想让浏览器不能直接访问到图片,可以放在WEB-INF下
                        String uploadPath=request.getSession().getServletContext().getRealPath("/upload");
    
                        File file=new File(uploadPath);
                        file.mkdirs();
                        //写入文件到磁盘,该行执行完毕后,若有该临时文件,将会自动删除
                        fileItem.write(new File(uploadPath,uuid+suffix));
                        
                    }
                }
            }  catch (Exception e) {
                e.printStackTrace();
            }
        }
    
        protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            doPost(request,response);
        }
    }
    

    参考博客:https://blog.csdn.net/fsdadsadas/article/details/73162677

                      https://www.cnblogs.com/lxboy2009/p/5994743.html

    展开全文
  • java常见3种文件上传方式

    万次阅读 热门讨论 2018-05-08 19:31:14
    转:https://www.cnblogs.com/Sunne/p/8086178.html在java里面文件上传的方式很多,最简单的依然是FileInputStream、FileOutputStream了,在这里我列举3种常见的文件上传方法代码,并比较他们的上传速度(由于代码是...

    转:https://www.cnblogs.com/Sunne/p/8086178.html

    在java里面文件上传的方式很多,最简单的依然是FileInputStream、FileOutputStream了,在这里我列举3种常见的文件上传方法代码,并比较他们的上传速度(由于代码是在本地测试,所以忽略网速的影响)

    还是老规矩,大神请绕一下,里屋说话。

    首先呢,使用springMVC原生上传文件方法,需要一些简单的配置,不多说,上图。

    1.采用spring提供的上传文件的方法

    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
    @RequestMapping("springUpload")
        public String  springUpload(HttpServletRequest request) throws IllegalStateException, IOException
        {
             long  startTime=System.currentTimeMillis();
             //将当前上下文初始化给  CommonsMutipartResolver (多部分解析器)
            CommonsMultipartResolver multipartResolver=new CommonsMultipartResolver(
                    request.getSession().getServletContext());
            //检查form中是否有enctype="multipart/form-data"
            if(multipartResolver.isMultipart(request))
            {
                //将request变成多部分request
                MultipartHttpServletRequest multiRequest=(MultipartHttpServletRequest)request;
               //获取multiRequest 中所有的文件名
                Iterator iter=multiRequest.getFileNames();
                  
                while(iter.hasNext())
                {
                     
                    //一次遍历所有文件
                    MultipartFile file=multiRequest.getFile(iter.next().toString());
                    if(file!=null)
                    {
                        String path="E:/springUpload"+file.getOriginalFilename();
                        //上传
                        file.transferTo(new File(path));
                    }
                      
                }
                
            }
            long  endTime=System.currentTimeMillis();
            System.out.println("Spring方法的运行时间:"+String.valueOf(endTime-startTime)+"ms");
            return "/success"
        }

      在这里故意加一个计时,待会就用它简单的比较上传时间问题(本人暂时还没能力处理资源占用问题,所以这里也不做比较)

    2.第二位选手,采用file.Transto 来保存上传的文件,这是目前我认为最好的上传方式,也是我最喜欢的上传方式,代码简单,速度快。请看下面代码。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    /*
         * 采用file.Transto 来保存上传的文件
         */
        @RequestMapping("fileUpload2")
        public String  fileUpload2(@RequestParam("file") CommonsMultipartFile file) throws IOException {
             long  startTime=System.currentTimeMillis();
            System.out.println("fileName:"+file.getOriginalFilename());
            String path="E:/"+new Date().getTime()+file.getOriginalFilename();
              
            File newFile=new File(path);
            //通过CommonsMultipartFile的方法直接写文件(注意这个时候)
            file.transferTo(newFile);
            long  endTime=System.currentTimeMillis();
            System.out.println("采用file.Transto的运行时间:"+String.valueOf(endTime-startTime)+"ms");
            return "/success"
        }

      3.第三种采用流的方式上传,这种方法在新手学习的时候经常用到,但是我并不喜欢,因为它又慢又难写,请看

    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
    @RequestMapping("fileUpload")
        public String  fileUpload(@RequestParam("file") CommonsMultipartFile file) throws IOException {
              
            //用来检测程序运行时间
            long  startTime=System.currentTimeMillis();
            System.out.println("fileName:"+file.getOriginalFilename());
              
            try {
                //获取输出流
                OutputStream os=new FileOutputStream("E:/"+new Date().getTime()+file.getOriginalFilename());
                //获取输入流 CommonsMultipartFile 中可以直接得到文件的流
                InputStream is=file.getInputStream();
                byte[] bts = new byte[1024];
                //一个一个字节的读取并写入
                while(is.read(bts)!=-1)
                {
                    os.write(bts);
                }
               os.flush();
               os.close();
               is.close();
              
            catch (FileNotFoundException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            long  endTime=System.currentTimeMillis();
            System.out.println("采用流上传的方式的运行时间:"+String.valueOf(endTime-startTime)+"ms");
            return "/success"
        }

      方法写好了,接下来,我们在本地做个简单的评测,

      1.写个简单的文件上传页面

        

      2.分别选择同一个文件,稍微大一点(我这里上传的zookeeper3.3.6的安装包,大小为11M),以区别处他们的耗时差异(最好不实用ie,很容易崩溃,亲测)

      

      3.统计耗时,请看下图,结果一目了然。

     

     在此补充说明一点,如果你认为采用流的方式上传慢是因为我这里内存开辟小了,可以尝试开大一点,但是依然不影响他的速度最慢的地位,如果内存开的过大,反倒影响速度。

    以上内容仅供学习,如果有需要源码的,请联系我。


    展开全文
  • Spring Boot教程(十三):Spring Boot文件上传

    万次阅读 多人点赞 2018-05-15 15:55:31
    一、创建一个简单的包含WEB依赖的SpringBoot项目 pom.xml内容: &lt;!-- Spring Boot web启动器 --&gt; &lt;dependency&gt; &lt;groupId&...spring-boot-starter-...
  • 文件上传与下载

    2020-11-19 21:00:24
    文件上传</a><br/> <body> <h2>文件上传</h2> <center> <form action="file/upload1" method="post" id="itmesForm" enctype="multipart/form-data" > <input t...
  • 文件上传下载

    2020-07-23 17:22:14
    上传 javaScript str3 +='<div id="fileDiv" class="my-input-box" style="width:80%"><div class="label-box"><label class="test">文件:</label></div>'; str3 +='<div>';...
  • 文件上传

    2020-11-19 15:19:04
    3.图片改变文件上传每次点上传都是一种图片改变。 对应图片改变,就要进行相关的处理, a.图片大小 b.图片格式 等等 对于这些处理都应确保逻辑的完整性。 为何这样做,起到什么效果,处理了什么事情 4.图片...
  • 文件上传 这里参考阮一峰老师的博客,原文写于2012年,现在需要不断学习新东西。 早期不同文件上传浏览器兼容性不好。现在HTML5出现后有了统一的接口。 1、早期 form 表单同步上传 &lt;form id="upload-...
  • 微服务文件上传下载方案

    千次阅读 2018-11-14 19:47:04
    文件上传: (1) 前端使用ant design上传组件完成上传, 直接点击按钮提交, 上传成功后需要服务端返回成功标识;   (2) 后端提供独立的服务,   (3) 需要判断权限,预留接口   (4) 上传下载的表本身与...
  • javaweb文件上传与下载

    万次阅读 热门讨论 2018-08-24 14:14:53
    一、文件上传 要实现Web开发的上传功能,通常需要完成两步操作:一是在Web页面中添加上传输入项;二是在Servlet中读取上传文件的数据,并保存到本地硬盘中。 上传大多数情况是通过表单的形式提交给服务器,使用&...
  • 对于文件上传,浏览器在上传的过程中是将文件以流的形式提交到服务器端的,如果直接使用Servlet获取上传文件的输入流然后再解析里面的请求参数是比较麻烦,所以一般选择采用apache的开源工具common-fileupload这个...
  • Java实现上传(支持多个文件同时上传)和下载

    万次阅读 多人点赞 2018-05-08 17:38:41
    文件上传一直是Web项目中必不可少的一项功能。项目结构如下:(这是我之前创建的SSM整合的框架项目,在这上面添加文件上传与下载)主要的是FileUploadController,doupload.jsp,up.jsp,springmvc.xml1.先编写up.jsp&...
  • 文件上传步骤

    千次阅读 2019-02-17 16:30:41
    前提条件:文件上传必须使用form表单; 文件上传页面的三要素: form表单必须是post方式; enctype必须等于“multipart/form-data”; 必须提供一个type=“file"的文件上传项; 1&gt;.导入fileupload包; 2&...
  • 文件上传漏洞

    万次阅读 2019-03-04 00:27:45
    文件上传漏洞 文件上传漏洞是指由于程序员未对上传的文件进行严格的验证和过滤,而导致的用户可以越过其本身权限向服务器上上传可执行的动态脚本文件。这里上传的文件可以是木马,病毒,恶意脚本或者WebShell等。...
  • Web安全-文件上传漏洞

    千次阅读 多人点赞 2018-12-29 10:15:51
    文件上传漏洞是指用户上传了一个可执行的脚本文件,并通过此脚本文件获得了执行服务器端命令的能力。这种攻击方式是最为直接和有效的,“文件上传”本身没有问题,有问题的是文件上传后,服务器怎么处理、解释文件。...
  • php文件上传漏洞

    千次阅读 2019-03-06 12:28:59
    文件上传漏洞 文件上传漏洞是指由于服务器对于用户上传部分的控制不严格导致攻击者可以上传一个恶意的可执行的文件到服务器。简单点说,就是用户直接或者通过各种绕过方式将webshell上传到服务器中进而执行利用。 ...
  • 文件上传漏洞小总结

    千次阅读 2019-10-28 21:13:45
    一、什么是文件上传漏洞 文件上传漏洞是指由于程序员在对用户文件上传部分的控制不足或者处理缺陷,而导致的用户可以越过其本身权限向服务器上传可执行的动态脚本文件。这里上传的文件可以是木马,病毒,恶意脚本...
  • 文件上传漏洞攻击与防范方法

    万次阅读 多人点赞 2019-08-30 17:04:20
    文件上传漏洞攻击与防范方法 文件上传漏洞简介: 文件上传漏洞是web安全中经常用到的一种漏洞形式。是对数据与代码分离原则的一种攻击。上传漏洞顾名思义,就是攻击者上传了一个可执行文件如木马,病毒,恶意脚本,...
  • 文件上传漏洞原理和利用

    千次阅读 2019-08-06 19:03:45
    文件上传 1.前段选择文件,提交文件 2.浏览器形成POST MultiPart报文发送到服务器 ...文件上传漏洞 1.未对上传文件进行严格的验证和过滤时,容易造成动态文件asp/php/jsp等等 2.如果上传的目标目录没...
  • 文件上传漏洞是什么?怎样防御文件上传漏洞攻击?文件上传漏洞是web安全中经常利用到的一种漏洞形式。这种类型的攻击从大的类型上来说,是攻击 数据与代码分离原则 的一种攻击。 一些web应用程序中允许上传图片,...
  • 文件上传检测分类 任意上传 前端JS检测 文件扩展名检测 MIME-type检测 文件头检测 文件加载检测 1、任意上传概念: 服务端脚本语言未对上传的...
  • PHP文件上传漏洞

    千次阅读 2018-11-01 21:53:01
    PHP文件上传漏洞: 在PHP版本小于5.3.4的move_uploaded_file()函数中,存在CVE-2006-7243这个漏洞。 -形成原因:move_uploaded_file()底层源码用c编写,判断上传文件路径的时候使用了char指针,C语言中char...
  • 文件上传漏洞绕过手段

    万次阅读 2018-06-12 18:20:40
    文件上传漏洞的成因:1.服务器的错误配置2.开源编码器漏洞3.本地上传上限制不严格被绕过4.服务器端过滤不严格被绕过常见上传检测流程2.文件上传漏洞的危害(1)网站被控制(2)服务器沦陷(3)同服务器的其他网站...
  • 文件上传漏洞原理与实例测试

    千次阅读 2016-07-22 17:32:57
    0x00 什么是文件上传 为了让用户将文件上传到网站,就像是给危机服务器的恶意用户打开了另一扇门。即便如此,在今天的现代互联网的Web应用程序,它是一种常见的要求,因为它有助于提高业务效率。企业...
  • 一、 文件上传漏洞与WebShell的关系 文件上传漏洞是指网络攻击者上传了一个可执行的文件到服务器并执行。这里上传的文件可以是木马,病毒,恶意脚本或者WebShell等。这种攻击方式是最为直接和有效的,部分文件上传...
  • 文件上传漏洞(绕过姿势)

    千次阅读 2018-06-23 10:52:28
    文件上传漏洞可以说是日常渗透测试用得最多的一个漏洞,因为用它获得服务器权限最快最直接。但是想真正把这个漏洞利用好却不那么容易,其中有很多技巧,也有很多需要掌握的知识。俗话说,知己知彼方能百战不殆,因此...
  • BugkuCTF:文件包含2 CTF实战练习:http://120.78.xx.xxx:8013 这道题目看起来又像是跟前一道题是差不多的样子,继续先查看index.php里面的内容: 哎~这次好像显示的并不是base64编码的内容,但是感觉起来这个...

空空如也

1 2 3 4 5 ... 20
收藏数 1,089,626
精华内容 435,850
关键字:

文件上传