ajax formData 上传文件,Servlet 获取文件和参数的方式

公司项目框架比较老,遇到一个上传文件的问题,记录一下解决方式。

前端使用formData上传文件:

let formData = new FormData();
// 向formData中添加数据
formData.append("id", this.userHelperForm.id);
formData.append("name", this.userHelperForm.name);
formData.append("imageUrl", this.userHelperForm.imageUrl);
formData.append("file", this.fileList[0].raw);
formData.append("type", this.userHelperForm.type);
formData.forEach((value, key) => {
	console.log("key %s: value %s", key, value);
});
let url = "UserHelperSubmitServlet";
$.ajax({
	url: url,
	type: "POST",
	cache: false,
	data: formData,
	processData: false,
	contentType: false,
})
	.done(function (res) {
		console.log(res);
	})
	.fail(function (res) {});

这里contentType设置为false就行,似乎会默认转为:multipart/form-data

主要问题在后端,

如果参数中不传文件,即

Content-Type="application/x-www-form-urlencoded" 时,可以直接使用request.getParamter()获取参数。

如果参数中不传文件,但是 

Content-Type="multipart/form-data"

也可以通过以下方式去获取参数(当然最好还是直接改成application/x-www-form-urlencoded 即可解决问题):

String contentType = request.getContentType();
if (contentType != null && contentType.contains("multipart/form-data")) {
    MultipartResolver resolver = new CommonsMultipartResolver(request.getSession().getServletContext());
    //将转化后的 request 放入过滤链中
    request = resolver.resolveMultipart(request);
}

将requset转换一次即可通过 

request.getParameter(xxx)

去获取。

但是如果参数中既有字段,又有文件怎么办?

使用Servlet上传文件时,获取文件菜鸟教程给出的方式如下:

Servlet 文件上传 | 菜鸟教程

核心部分即:

//创建磁盘工厂对象
DiskFileItemFactory factory = new DiskFileItemFactory();
//Servlet文件上传核心对象
ServletFileUpload fileUpload = new ServletFileUpload(factory);
List<FileItem> fileItems = fileUpload.parseRequest(request);

拿到 fileItem以后,再通过InputStream上传文件,这里给出一段代码样例:

    public String saveFile(FileItem file) {
        //判空
        if (file == null) {
            throw new SmartbiException(SJMHErrorCode.UPLOAD_FiLE_EMPTY);
        } else {
            String dateStr = dateFormat.format(new Date());
            String uuid = UUIDGenerator.generate();
            //文件名 日期+UUID+后缀名 eg: 2023_03_09_18_30_26_I40287aa50186785f785f1dfb018678642d930014.pdf
            String fileName = timeFormat.format(new Date()) + "_" + uuid + "." + FileUtil.getSuffix(file.getName());
            StringBuilder filePath = new StringBuilder();
            String nasPath = NasUtil.getPath();
            //路径格式 path/2023-03-09
            filePath.append(nasPath)
                    .append(nasPath.endsWith(File.separator) ? "" : File.separator)
                    .append(dateStr);
            try {
                file.getInputStream();
            } catch (IOException e) {
                logger.error("获取不了");
                throw new RuntimeException(e);
            }
            //上传文件 全路径eg:path/2023-03-09/2023_03_09_18_30_26_I40287aa50186785f785f1dfb018678642d930014.pdf
            try {
                NasUtil.uploadFile(file.getInputStream(), filePath.toString(), fileName);
            } catch (Exception e) {
                throw new SmartbiException(SJMHErrorCode.UPLOAD_FILE_FAIL, e);
            }
            //保存文件上传记录
            saveUploadFileRecord(uuid, fileName, filePath.toString());
            logger.info("上传成功!! 文件路径:" + filePath);
            return uuid;
        }
    }

如果要同时获取文件和参数,就需要直接遍历FileItem

public class UserHelperSubmitServlet extends HttpServlet {
    private static final Logger logger = LoggerFactory.getLogger(UserHelperSubmitServlet.class);
    private static final UserHelperService userHelperService = UserHelperService.getInstance();

    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws IOException {
        try {
            //创建磁盘工厂对象
            DiskFileItemFactory factory = new DiskFileItemFactory();
            //Servlet文件上传核心对象
            ServletFileUpload fileUpload = new ServletFileUpload(factory);
            List<FileItem> fileItems = fileUpload.parseRequest(request);
            Map<String, Object> params = new HashMap<>();
            //只能在这里获取参数 因为getParameter、getInputStream和getReader是互斥的,当流被其中一种方式读取后可能字节发生了改变,这时候用另外一种方法无论如何都获取不到的
            //所以在 fileUpload.parseRequest(request) 之后 即时用下方注释掉的代码处理request后 再尝试使用 request.getParameter去获取参数 会发现也都是null
            for (FileItem fileItem : fileItems) {
                //是普通表单字段
                if (fileItem.isFormField()) {
                    logger.info(fileItem.getFieldName() + " - " + fileItem.getString("UTF-8"));
                    params.put(fileItem.getFieldName(), fileItem.getString("UTF-8"));
                } else {
                    //是文件 这里只上传一个文件 所以无需List处理
                    params.put(fileItem.getFieldName(), fileItem);
                    logger.info(fileItem.getName());
                }
            }

//            Content-Type="application/x-www-form-urlencoded"是默认的编码方式 如果是这种编码方式 可以使用 request.getParameter 获取参数信息
//            由于前端是表单提交 formData包含文件 即 Content-Type="multipart/form-data" 所以正常使用 request.getParameter无法获取参数 会发现都是null
//            这一段代码的作用就是用来处理formData,处理后就可以正常使用 request.getParameter 获取字段信息,但是如果其中有文件 就无法获取文件  所以没使用这个方案

//            String contentType = request.getContentType();
//            if (contentType != null && contentType.contains("multipart/form-data")) {
//                MultipartResolver resolver = new CommonsMultipartResolver(request.getSession().getServletContext());
//                // 将转化后的 request 放入过滤链中
//                request = resolver.resolveMultipart(request);
//            }


            String id = (String) params.get("id");
            String name = (String) params.get("name");
            String imageUrl = (String) params.get("imageUrl");
            int type = Integer.parseInt((String) params.get("type"));
            FileItem uploadFile = (FileItem) params.get("file");

            userHelperService.saveOrUpdate(id, name, imageUrl, uploadFile, type);

            Result result = new Result(0, "文件上传成功!");
            response.getOutputStream()
                    .write(JSONObject.fromObject(result).toString().getBytes(StandardCharsets.UTF_8));
        } catch (Exception e) {
            logger.error(e.getMessage(), e);
            Result result = new Result(-1, "文件上传失败," + e.getMessage());
            response.getOutputStream().write(JSONObject.fromObject(result).toString().getBytes(StandardCharsets.UTF_8));
        }
    }
}

猜你喜欢

转载自blog.csdn.net/qq_16382227/article/details/129439281