jsp+servlet 实现上传文件功能

jsp部分

enctype 属性是规定在发送到服务器之前应该如何对表单数据进行编码。
enctype常用的属性值有3个:第一个是application/x-www-form-urlencoded,这是默认的编码方式,它只处理表单域里的value属性值,采用这种编码方式的表单会将表单域的值处理成URL编码方式,第二种是multipart/form-data,这种编码方式的表单会以二进制流的方式来处理表单数据,同时,这种编码方式也会把文件域指定文件的内容封装到请求参数里,第三种就是text/plain,这种方式主要适合用于直接通过表单发送邮件的方式。

上传文件的表单必须设置 enctype 为 multipart/form-data 类型(让表单提交的数据以二进制编码的方式提交,在接收此请求的Servlet中用二进制流来获取内容,就可以取得上传文件的内容,从而实现文件的上传)且method只能为post,不能为get。如果想要多文件上传,可以给文本域添加 multiple=”multiple” 属性。

如果想限制用户可以选择文件的格式,只需要添加 accept=”image/gif,image/png” 即可。

<form method="post" enctype="multipart/form-data">
    <input type="file" name="upload_media" class="upload_media" multiple="multiple" />
    <button type="submit">上传文件</button>
</form>



我们可以给文本域绑定一个事件,当其值发生改变的时候,我们验证用户选择的文件是否合法。

$(function(){
    $('.upload_media').change(function(){
        var files = $(this)[0].files;
        for(var i = 0, f; f = files[i]; i++){
            if(f.type == 'image/png' || f.type == 'image/gif' || f.type == 'image/jpg' || f.type == 'image/jpeg'){
                if(f.size < 2*1024*1024){
                    //如果需要自动提交表单,可以使用下面的这行代码,否者就等到用户点击按钮再上传文件
                    //$('.upload_media').parent().submit();
                }else{
                    alert(f.name + '文件超出上传大小限制!');
                }
            }else{
                alert(f.name + '不是图片!');
            }
    })
})

以上内容出自-在web网页中开发上传文件功能,里面还有ajax上传文件的内容,有兴趣的话可以看一下。

关于以上代码的理解:
——${}是什么意思?
一般来说,$是jQuery的别名,但是$()根据括号里传入的参数不同,执行的内容完全不同。
例如:

var $ = function(id){
    return document.getElementById(id);
}

那么运行$(id) 就等于运行了document.getElementById(id)

$()的具体用法可以看:jQuery中$()函数的用法小结
这里就只介绍上文代码中的用法。

$('.upload_media').change():这里的.upload_media是css选择器,对应input type=”file” 中的class=”upload_media”,一旦选择了文件,就会触发change这个事件,里面的代码将会监听change事件。$(this)是被jquery包着的input元素,$(this)[0]就是input元素,后面的for就是在遍历多个文件了。

而第一个$()是以下这种用法:

通常JavaScript需要在DOM加载完成后执行,否则DOM操作可能会失效。jQuery提供了一个方便的方法来监听DOM加载完成

// 方法声明
jQuery( callback )
// 例子
$(function(){
    // DOM载入后执行
});

$(callback)的作用完全相当于$(document).ready(callback)

解释一下上面这段文字:浏览器是从上往下解析整个页面的,如果现在有一个场景:

<script>document.getElementById('A').value = '123'</script>
<input id="A"/>

这个js在这个input上面,那么会先解析js,去获取那个节点,,但是节点在下面还没生成呢,于是就报错了。为了解决这个问题,就需要在dom加载完成后再做相应的获取dom操作,这就是$.ready的目的。(这样它就可以放在代码的任意位置不出现问题)

当然,要先用js标签引入jQuery,不然会认不出$
注:必须要用 <script src="..."></script> 的形式引入jQuery,而不能用<script src="..."/>的形式引入jQuery
引入jQuery:

1.引用在线jQuery
谷歌、微软、百度都有提供在线的jQuery引用。比如
<script src="http://code.jquery.com/jquery-latest.js"></script>
2.引用本地的jQuery。
先在下载jQuery.js文件或者jQuery.min.js文件(这个是压缩版的),放在项目中。
假如jQuery文件和当前js、html文件位于同一目录下,可以直接写jQuery的文件名。比如
<script src="jquery-3.2.1.min.js"></script>
如果jQuery文件和当前的js、html文件不是位于同一目录下,可以通过 .. 先返回上一层目录再引入jQuery。比如:
<script src="../jquery-3.2.1.min.js"></script>
另外,如果你使用的是Intellij Idea或者WebStrom等,可以直接将jQuery文件拖拉进当前代码中,会自动生成相关路径。

来自:引入jQuery的src设置

servlet部分

以下代码来自用jsp+servlet实现文件的上传与下载

package com.dw.servlet;  

import java.io.File;  
import java.io.FileOutputStream;  
import java.io.IOException;  
import java.io.InputStream;  
import java.io.RandomAccessFile;  
import javax.servlet.RequestDispatcher;  
import javax.servlet.ServletException;  
import javax.servlet.http.HttpServlet;  
import javax.servlet.http.HttpServletRequest;  
import javax.servlet.http.HttpServletResponse;  

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 {  
        request.setCharacterEncoding("utf-8");  
        response.setCharacterEncoding("utf-8");  
        response.setContentType("text/html;charset=utf-8");//更改响应字符流使用的编码,还能告知浏览器用什么编码进行显示  

        //从request中获取文本输入流信息  
        InputStream fileSourceStream = request.getInputStream();  
        String tempFileName = "F:/tempFile";  

        //设置临时文件,保存待上传的文本输入流  
        File tempFile = new File(tempFileName);  

        //outputStram文件输出流指向这个tempFile  
        FileOutputStream outputStream = new FileOutputStream(tempFile);  

        //读取文件流  
        byte temp[] = new byte[1024];  
        int n;  
        while(( n = fileSourceStream.read(temp)) != -1){  
            outputStream.write(temp, 0, n);  
        }  
        outputStream.close();  
        fileSourceStream.close();  

        //获取上传文件的名称   
        RandomAccessFile randomFile = new RandomAccessFile(tempFile,"r");  
        randomFile.readLine();    
        String str = randomFile.readLine();  
        int start = str.lastIndexOf("=") + 2;  
        int end = str.lastIndexOf("\"");  
        String filename = str.substring(start, end);  

        //定位文件指针到文件头  
        randomFile.seek(0);  
        long startIndex = 0;  
        int i = 1;  
        //获取文件内容的开始位置  
        while(( n = randomFile.readByte()) != -1 && i <=4){  
            if(n == '\n'){  
                startIndex = randomFile.getFilePointer();  
                i ++;  
            }  
        }  
        startIndex = startIndex -1; //这里一定要减1,因为前面多读了一个,这里很容易忽略  
        //获取文件内容结束位置  
        randomFile.seek(randomFile.length());  
        long endIndex = randomFile.getFilePointer();  
        int j = 1;  
        while(endIndex >=0 && j<=2){  
            endIndex--;  
            randomFile.seek(endIndex);  
            if(randomFile.readByte() == '\n'){  
                j++;  
            }  
        }  

        //设置保存上传文件的路径  
        String realPath =  "F:/file";  
        File fileupload = new File(realPath);  
        if(!fileupload.exists()){  
            fileupload.mkdir();  
        }  
        File saveFile = new File(realPath,filename);  
        RandomAccessFile randomAccessFile = new RandomAccessFile(saveFile,"rw");  
        //根据起止位置从临时文件中读取文件内容  
        randomFile.seek(startIndex);  
        while(startIndex < endIndex){  
            randomAccessFile.write(randomFile.readByte());  
            startIndex = randomFile.getFilePointer();  
        }  
        //关闭输入输出流并 删除临时文件  
        randomAccessFile.close();  
        randomFile.close();  
        tempFile.delete();  

        request.setAttribute("result", "文件上传成功");  
        RequestDispatcher dispatcher = request.getRequestDispatcher("index.jsp");  
        dispatcher.forward(request, response);  
    }  

}  

以下内容来自菜鸟教程-jsp文件上传

以下是 UploadServlet 的源代码,同于处理文件上传,在这之前我们先确保依赖包已经引入到项目的 WEB-INF/lib 目录下:

下面的实例依赖于 FileUpload,所以一定要确保在您的 classpath 中有最新版本的 commons-fileupload.x.x.jar 文件。可以从 http://commons.apache.org/proper/commons-fileupload/ 下载。
FileUpload 依赖于 Commons IO,所以一定要确保在您的 classpath 中有最新版本的 commons-io-x.x.jar 文件。可以从 http://commons.apache.org/proper/commons-io/ 下载。

package com.runoob.test;

import java.io.File;
import java.io.IOException;
import java.io.PrintWriter;
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.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;


/**
 * Servlet implementation class UploadServlet
 */
@WebServlet("/UploadServlet")
public class UploadServlet extends HttpServlet {
    private static final long serialVersionUID = 1L;

    // 上传文件存储目录
    private static final String UPLOAD_DIRECTORY = "upload";

    // 上传配置
    private static final int MEMORY_THRESHOLD   = 1024 * 1024 * 3;  // 3MB
    private static final int MAX_FILE_SIZE      = 1024 * 1024 * 40; // 40MB
    private static final int MAX_REQUEST_SIZE   = 1024 * 1024 * 50; // 50MB

    /**
     * 上传数据及保存文件
     */
    protected void doPost(HttpServletRequest request,
        HttpServletResponse response) throws ServletException, IOException {
        // 检测是否为多媒体上传
        if (!ServletFileUpload.isMultipartContent(request)) {
            // 如果不是则停止
            PrintWriter writer = response.getWriter();
            writer.println("Error: 表单必须包含 enctype=multipart/form-data");
            writer.flush();
            return;
        }

        // 配置上传参数
        DiskFileItemFactory factory = new DiskFileItemFactory();
        // 设置内存临界值 - 超过后将产生临时文件并存储于临时目录中
        factory.setSizeThreshold(MEMORY_THRESHOLD);
        // 设置临时存储目录
        factory.setRepository(new File(System.getProperty("java.io.tmpdir")));

        ServletFileUpload upload = new ServletFileUpload(factory);

        // 设置最大文件上传值
        upload.setFileSizeMax(MAX_FILE_SIZE);

        // 设置最大请求值 (包含文件和表单数据)
        upload.setSizeMax(MAX_REQUEST_SIZE);

        // 中文处理
        upload.setHeaderEncoding("UTF-8"); 

        // 构造临时路径来存储上传的文件
        // 这个路径相对当前应用的目录
        String uploadPath = getServletContext().getRealPath("/") + File.separator + UPLOAD_DIRECTORY;


        // 如果目录不存在则创建
        File uploadDir = new File(uploadPath);
        if (!uploadDir.exists()) {
            uploadDir.mkdir();
        }

        try {
            // 解析请求的内容提取文件数据
            @SuppressWarnings("unchecked")
            List<FileItem> formItems = upload.parseRequest(request);

            if (formItems != null && formItems.size() > 0) {
                // 迭代表单数据
                for (FileItem item : formItems) {
                    // 处理不在表单中的字段
                    if (!item.isFormField()) {
                        String fileName = new File(item.getName()).getName();
                        String filePath = uploadPath + File.separator + fileName;
                        File storeFile = new File(filePath);
                        // 在控制台输出文件的上传路径
                        System.out.println(filePath);
                        // 保存文件到硬盘
                        item.write(storeFile);
                        request.setAttribute("message",
                            "文件上传成功!");
                    }
                }
            }
        } catch (Exception ex) {
            request.setAttribute("message",
                    "错误信息: " + ex.getMessage());
        }
        // 跳转到 message.jsp
        getServletContext().getRequestDispatcher("/message.jsp").forward(
                request, response);
    }

猜你喜欢

转载自blog.csdn.net/yogima/article/details/80330993