会社のプロジェクト フレームワークは比較的古いため、ファイルのアップロードで問題が発生した場合は、解決策を記録します。
フロントエンドは 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));
}
}
}