Ajax使用FormData对象上传文件的两种方式

  1. 以下是Demo的项目结构:主要就是一个servlet3.0和一个jsp页面
    这里写图片描述
  2. 由于使用的是servlet3.0,所以无需配置web.xml,以下是idnex.jsp页面:
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%
    String path = request.getContextPath();
    String basePath = request.getScheme() + "://" + request.getServerName() + ":" + request.getServerPort()
            + path + "/";
%>
<!DOCTYPE html>
<html>
<head>
<base href="<%=basePath%>">
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>文件上传demo</title>
<style type="text/css">
h1 {
    text-align: center;
    text-shadow: 2px 2px 2px #999;
}

a {
    text-decoration: none;
    position: relative;
    display: block;
    width: 100px;
    height: 30px;
    line-height: 30px;
    background: #EEE;
    border: 1px solid #999;
    text-align: center;
    background: #EEE;
}

input {
    position: absolute;
    border-radius: 10px;
    left: 0;
    top: 0;
    width: 100%;
    height: 100%;
    z-index: 999;
    opacity: 0;
}

#myDiv {
    margin: auto;
    width: 100px;
    height: 30px;
}

a:HOVER {
    background: red;
}

.fileList {
    width: 600px;
    height: 400px;
    overflow: auto;
    position: absolute;
    bottom: 20px;
    right: 20px;
    position: absolute;
    border: 1px solid blue;
    position: absolute;
}

ul {
    list-style: none;
}

ul:after {
    clear: both;
    content: "";
    display: block;
}

ul:nth-child(odd) {
    background: #677077;
    color: #fff;
}

li {
    float: left;
}
</style>

</head>
<body>
    <h1>文件上传demo</h1>
    <div id="myDiv">
        <a href="javascript:;" id="fileUpload">文件上传
         <input type="file" multiple onchange="fileChange(this)" />
        </a>
    </div>
    <div class="fileList" id="fileList">
        <ul>
            <li style="width: 30%">文件名</li>
            <li style="width: 68%">上传情况</li>
        </ul>
    </div>
</body>
<script>
    function fileChange(fileInput) {
        var files = fileInput.files;
        var tempHtml = "";
        for (var i = 0; i < files.length; i++) {
            var file = files[i];
            tempHtml += "<ul>"
                    + "<li style='width: 30%'>"
                    + file.name
                    + "</li>"
                    + "<li style='width: 68%'><progress id='p"+i+"' max='100' value=''></progress><span id='sp"+i+"'></span></li></ul>";
            fileUpload(file, i);
        }
        document.getElementById("fileList").innerHTML += tempHtml;
    }
    function fileUpload(file, index) {
        var formData = new FormData();
        formData.append(file.name, file);
        var xhr = new XMLHttpRequest();
        var oldUploaded=0;
        var curUploaded=0;
        var total=0;
        var percent=0;
        xhr.upload.addEventListener("progress",function(event){
            var loaded=event.loaded;
            if(oldUploaded==0){
                total=event.total;
                oldUploaded=event.loaded;
            }
            curUploaded=event.loaded;
            percent=Math.round(event.loaded/event.total*100);
            document.getElementById("p"+index).value=percent;
        });
        var upSpeed=setInterval(function(){
            if(oldUploaded!=0){
                //得到的是一个byte值
                var result=curUploaded-oldUploaded;
                var leave=total-curUploaded;
                var label=document.getElementById("sp"+index);
                label.innerHTML=percent+"%&nbsp;&nbsp;"+Math.round(result/(1024*1024)*100)/100+"M/S&nbsp;&nbsp;剩余"+Math.round(leave/result)+"秒";
                if(total==oldUploaded&&result==0){
                    clearInterval(upSpeed);
                }
                oldUploaded=curUploaded;
            }
        },1000);
        xhr.open("post", "FileUp", true);
        xhr.send(formData);
    }
</script>
</html>

3.FileUp.java类代码如下:

package com.prosay.upload;

import java.io.File;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Collection;
import java.util.List;

import javax.servlet.ServletException;
import javax.servlet.annotation.MultipartConfig;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.Part;

import org.apache.tomcat.util.http.fileupload.FileItem;
import org.apache.tomcat.util.http.fileupload.disk.DiskFileItemFactory;
import org.apache.tomcat.util.http.fileupload.servlet.ServletFileUpload;
import org.apache.tomcat.util.http.fileupload.servlet.ServletRequestContext;

/**
 * 文件上传
 */

@WebServlet("/FileUp") // servlet3.0的规范,使用注解无需配置web.xml
@MultipartConfig // 加上该注解标识这个servlet支持文件上传,否则request.getParts()返回空,后台无法接收到文件
public class FileUp extends HttpServlet {
    private static final long serialVersionUID = 1L;
    /**
     * 后台接收文件方式一,该方式需要@MultipartConfig注解
     */
    public void service(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
        request.setCharacterEncoding("utf-8");
        String savePath = request.getServletContext().getRealPath("/myFiles");
        Collection<Part> files = request.getParts();
        for (Part file : files) {
            file.write(savePath + "/" + file.getName());
        }

    }

    /**
     * 后台接收文件方式二,该方式无需@MultipartConfig注解
     */
    protected void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        request.setCharacterEncoding("utf-8");
        String savePath = request.getServletContext().getRealPath("/myFiles");
        DiskFileItemFactory factory = new DiskFileItemFactory();
        ServletFileUpload upload = new ServletFileUpload(factory);
        try {
            List<FileItem> items = upload.parseRequest(new ServletRequestContext(request));
            for (FileItem item : items) {
                if (!item.isFormField()) {
                    // System.out.println("savePath = " + savePath);
                    // System.out.println(item.getName());
                    // System.out.println(item.getFieldName());
                    item.write(new File(savePath + "/" + item.getFieldName()));
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

    }

}

注:上传文件测试的时候,这两种后台处理文件的方式任选其一即可,方式一简洁些,但是需要@MultipartConfig注解,而方式二就不需要该注解。

4.布署Demo到tomcat,启动tomcat以后,如果没报错,打开浏览器,访问:http://localhost:8080/0813upload/,效果如下图所示:
这里写图片描述
点击文件上传按钮,选择文件后,开始上传的效果图如下:
这里写图片描述
上传完成后,在本地磁盘的myFiles文件夹下可以看到上传成功的文件,如下图所示:
这里写图片描述

本例中需要注意的几个问题
①取消a标签onclick事件,因为实际上已经不需要a标签的onclick触发file的click了,而是直接就点击到file;
②file标签不需要再设置display:none隐藏,而是通过opacity:0让它完全透明,实际它是浮在a标签之上
③file标签设置position:absolute后要给left:0、top:0,否则file标签不会吻合覆盖a标签导致点击按钮的时候点不到file标签
④index.jsp页面html的声明要用h5的方式:,因为后面使用的进度条progress和FormData对象是h5中的新内容,h4中是没有的;<head></head>标签中还要加上<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">,否则页面会出现中文乱码
⑤在FileUp.java类中,如果使用方式一接受文件,一定不要忘记在类上面加上@MultipartConfig注解,否则Collection<Part> files = request.getParts()中的files集合就是空的;如果使用方式二来接受文件,List<FileItem> items = upload.parseRequest(request)这样写的话,items中就是空的,是取不到前台传过来的文件的,必须这样写:List<FileItem> items = upload.parseRequest(new ServletRequestContext(request)),request要通过ServletRequestContext类new出来放进去才可以,自己在网上查了好多资料都是前面那种错误的写法,后来又查了好久才找到后面这种正确的写法。在此特意总结一下,免得以后遇到走弯路了!

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值