ajax formData によるファイルのアップロード、サーブレットがファイルとパラメータを取得する方法

会社のプロジェクト フレームワークは比較的古いため、ファイルのアップロードで問題が発生した場合は、解決策を記録します。

フロントエンドは 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="マルチパート/フォームデータ"

次の方法でもパラメータを取得できます (もちろん、問題を解決するには 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);
}

リクエストを一度変換して渡す 

request.getParameter(xxx)

取得するため。

しかし、パラメータにフィールドとファイルの両方が含まれている場合はどうなるでしょうか?

サーブレットを使用してファイルをアップロードする場合、ファイルの新人チュートリアルを取得する方法は次のとおりです。

サーブレット ファイルのアップロード | 初心者向けチュートリアル

核心部分は次のとおりです。

//创建磁盘工厂对象
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