Ajax实现文件上传(解决upload.parseRequest为空问题)

本文介绍三种Ajax文件上传方法:使用fileupload组件、StandardMultipartHttpServletRequest类及第三方控件。涵盖前后端实现细节,并提供SpringBoot配置指导。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1.使用fileupload实现

这种方式也是目前网上主要绝大部分Ajax文件上传的方法,前台代码如下:

<!-- 定义上传按钮 -->
<input type="file" id="uploadFile">
<button onclick="uploadFile()" >上传文件</button>
<script>
    var fileSize;
    var fileName;

    // 动态获取文件名和文件大小,如果要做判断的话
    $("#uploadFile").change(function(){
        var file = this.files[0];
        fileName = file.name;
        fileSize = file.size;
    });

    function uploadFile() {
        var formData = new FormData();
        var file = document.getElementById("uploadFile").files[0];
        formData.append("file",file);
        formData.append("fileName",fileName);
        formData.append("fileSize",fileSize);

    // 省略掉了success和error的处理
        sendFile("/uploadFile",formData,true,function (res) {
        },function (XMLHttpRequest, textStatus, errorThrown) {
        });
    }

    function sendFile(_url, _data, _async, _successCallback, _errorCallback) {
    $.ajax({
        type: "post",
        async: _async,
            url: _url,
            dataType: 'json',
            // 告诉jQuery不要去处理发送的数据
            processData : false,
            // 告诉jQuery不要去设置Content-Type请求头
            contentType: false,
            data: _data,
            success: function (msg) {
                _successCallback(msg);
            },
            error: function (error) {
                _errorCallback(error);
            }
    });
</script>

在后台,首先导入commons-fileupload包,我还用到了connons-io包,一并导入。

<dependency>
    <groupId>commons-fileupload</groupId>
    <artifactId>commons-fileupload</artifactId>
    <version>1.3.1</version>
</dependency>
<dependency>
    <groupId>commons-io</groupId>
    <artifactId>commons-io</artifactId>
    <version>2.5</version>
</dependency>

controller层编写接口:

package jit.wxs.web;

import org.apache.commons.io.FileUtils;
import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletRequest;
import java.io.File;
import java.util.List;

/**
 * @author jitwxs
 * @date 2018/3/15 18:56
 */
@Controller
public class FileController {
    @PostMapping("/uploadFile")
    public String uploadFile(HttpServletRequest request) throws Exception {
        int sizeThreshold = 1024 * 1024;
        File repository = new File("/temp");

        // 创建磁盘文件项工厂,参数为缓存文件大小和临时文件位置
        DiskFileItemFactory factory = new DiskFileItemFactory(sizeThreshold, repository);

        // 创建文件上传核心类
        ServletFileUpload upload = new ServletFileUpload(factory);
        upload.setHeaderEncoding("UTF-8");

        // 判断是否是Multipart类型的
        if(ServletFileUpload.isMultipartContent(request)) {
            // 解析request并获得文件项集合
            List<FileItem> list = upload.parseRequest(request);
            if(list != null) {
                for(FileItem item : list) {
                    // 判断参数是普通参数还是文件参数
                    if(item.isFormField()) {
                        // 获得普通参数的key、value(即formData的fileName和fileSize)
                        String fieldName = item.getFieldName();
                        String fieldValue = item.getString("UTF-8");
                        System.out.println("FormField:k=" + fieldName + ",v=" + fieldValue);
                    } else {
                        //获得文件参数(即formData的file)
                        String fileName = item.getName();
                        String path = "/" + fileName;
                        // 上传文件
                        FileUtils.uploadFile(item,path);
                    }
                }
            }
        }

        return "返回给前台的消息";
    }
}

public static void uploadFile(FileItem item, String targetFilePath) throws IOException {
    InputStream in = item.getInputStream();
    OutputStream out = new FileOutputStream(targetFilePath);
    IOUtils.copy(in, out);
    in.close();
    out.close();

    // 删除临时文件
    item.delete();
}

当我项目环境是Spring MVC时这样用没有问题,当我更换为Spring Boot后在List<FileItem> list = upload.parseRequest(request);这个地方的值始终为null。最后我参考http://blog.youkuaiyun.com/u013248535/article/details/55823364这篇文章找到了解决方法。

2.使用StandardMultipartHttpServletRequest

直接将HttpServletRequest 强转为StandardMultipartHttpServletRequest,然后通过getFileNames()方法进行迭代,用这种方法不用使用common-fileupload包了,代码如下:

package jit.wxs.web;

import org.apache.commons.io.FileUtils;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.support.StandardMultipartHttpServletRequest;

import javax.servlet.http.HttpServletRequest;
import java.io.File;
import java.util.Iterator;

/**
 * @author jitwxs
 * @date 2018/3/15 18:56
 */
@RestController
public class FileController {
    @PostMapping("/uploadFile")
    public String uploadFile(HttpServletRequest request) throws Exception {
        StandardMultipartHttpServletRequest req = (StandardMultipartHttpServletRequest) request;

        // 遍历普通参数(即formData的fileName和fileSize)
        Enumeration<String> names = req.getParameterNames();
        while (names.hasMoreElements()) {
            String key = names.nextElement();
            String val = req.getParameter(key);
            System.out.println("FormField:k=" + key + "v=" + val);
        }

        // 遍历文件参数(即formData的file)
        Iterator<String> iterator = req.getFileNames();
        while (iterator.hasNext()) {
            MultipartFile file = req.getFile(iterator.next());
            String fileNames = file.getOriginalFilename();
            // 文件名
            fileNames = new String(fileNames.getBytes("UTF-8"));
            //int split = fileNames.lastIndexOf(".");
            // 文件前缀
            //String fileName = fileNames.substring(0, split);
            // 文件后缀
            //String fileType = fileNames.substring(split + 1, fileNames.length());
            // 文件大小
            //Long fileSize = file.getSize();
            // 文件内容
            byte[] content = file.getBytes();

            FileUtils.writeByteArrayToFile(new File(fileNames), content);
        }

        return "返回给前台的消息";
    }
}

这样就能够实现文件上传,如果出现大小超出限制的错误,记得在spring boot的配置文件中配置下:

# 上传单个文件最大允许
spring.servlet.multipart.max-file-size=10MB
# 每次请求最大允许
spring.servlet.multipart.max-request-size=100MB

3.使用文件上传控件

与其折腾半天为啥没法上传,不如使用别人的轮子,在条件允许的情况下,可以使用一些第三方的文件上传控件。推荐下我使用过的控件:

  • BootstrapFileInput

  • WebUploader

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值