通过 REST API 的多部分文件上传损坏文件并增加文件大小
Multipart File Upload via REST API corrupts file and increases file size
正在将文件(任何格式的 doc、docx、pdf、文本等)作为多部分 form/data 从 Postman 或应用程序 UI 上传到 REST API。文本文件上传正常。所有其他非文本格式都会损坏。我打不开那些文件。
上传文件的大小急剧增加。检查以下服务器日志:
File size just before call to request.getRequestDispatcher().forward(): 27583
Controller, first line in method:39439
上传的文件大小为27.3Kb
我猜测文件已损坏,因为附加到文件的其他数据。
控制器方法是
@RequestMapping(value="/entity/{entity}/{entityId}/type/{type}/{derive}",method = RequestMethod.POST)
@ResponseBody
public String uploadFile(@RequestParam("file") MultipartFile multipartFile,@PathVariable("entity")String entity,@PathVariable("type")String type,@PathVariable("entityId")Long entityId,@PathVariable("derive") boolean derive) throws Exception
由于文本文件保存正确,其他文件也正确写入,请不要认为写入文件的代码不正确。
获取输入流的代码
public String storeFile(MultipartFile multipartFile, String entity, Long id, String uploadType, boolean isDerive,String customName)
throws Exception
{
try
{
System.out.println(multipartFile.getSize());
String fileName = "";
String contentType = "";
if (multipartFile != null)
{
fileName = multipartFile.getOriginalFilename();
contentType = multipartFile.getContentType();
if (contentType == null)
{
contentType = "application/msword";
}
}
InputStream is = multipartFile.getInputStream();
String filePath = getFileName(entity, uploadType, id, fileName, isDerive,customName);
Helper.storeFile(is, filePath);
precedingPath = precedingPath.length() > 0 ? precedingPath + "/":"";
return precedingPath + filePath;
}
catch (WebException e)
{
e.printStackTrace();
throw e;
}
catch (Exception e)
{
e.printStackTrace();
throw new WebException(e.getMessage(), IHttpConstants.INTERNAL_SERVER_ERROR, e);
}
}
Helper.storeFile
public static File storeFile(InputStream is, String filePath) throws IOException {
try {
String staticRepoPath = null;
if (MasterData.getInstance().getSettingsMap().containsKey(Settings.REPO_LOCATION.toString())) {
staticRepoPath = MasterData.getInstance().getSettingsMap().get(Settings.REPO_LOCATION.toString());
} else {
throw new WebException("Invalid Settings");
}
byte[] buffer = new byte[is.available()];
is.read(buffer);
File targetFile = new File(staticRepoPath + File.separator + filePath);
@SuppressWarnings("resource")
OutputStream outStream = new FileOutputStream(targetFile);
outStream.write(buffer);
return targetFile;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
我的Ajax请求如下
var fd = new FormData();
//Take the first selected file
fd.append("file", document.actualFile);
//Generic AJAX call
CandidateService.ajax_uploadDocumentWithDocType($scope.candidate.id, fd, document.docType, function (error, json)
上传时的内容类型:
var config = {headers:{'X-Auth-Token':authToken, 'Content-Type': undefined}, transformRequest: angular.identity};
有人知道我该如何解决这个问题并成功上传文件吗?
Q1) 为什么请求调度器和处理文件数据的控制器之间的文件大小会发生变化。
Q2) 文件大小的这种变化是否是文件损坏的原因? Libre Office 导致常规 Input/Output 错误。
我发现了文件上传的问题。我在中间有一个 spring 过滤器,它正在将请求更改为 wrappedRequest。这是向多部分数据添加额外数据并导致文件损坏。
嗯,在我的例子中,我在通过亚马逊 API 网关访问 API 时遇到了完全相同的问题。结果我忘了在 API 网关上允许多部分 ContentType。
有点奇怪,请求仍然发送到我的服务器并且文本文件工作正常。
正在将文件(任何格式的 doc、docx、pdf、文本等)作为多部分 form/data 从 Postman 或应用程序 UI 上传到 REST API。文本文件上传正常。所有其他非文本格式都会损坏。我打不开那些文件。
上传文件的大小急剧增加。检查以下服务器日志:
File size just before call to request.getRequestDispatcher().forward(): 27583
Controller, first line in method:39439
上传的文件大小为27.3Kb
我猜测文件已损坏,因为附加到文件的其他数据。
控制器方法是
@RequestMapping(value="/entity/{entity}/{entityId}/type/{type}/{derive}",method = RequestMethod.POST)
@ResponseBody
public String uploadFile(@RequestParam("file") MultipartFile multipartFile,@PathVariable("entity")String entity,@PathVariable("type")String type,@PathVariable("entityId")Long entityId,@PathVariable("derive") boolean derive) throws Exception
由于文本文件保存正确,其他文件也正确写入,请不要认为写入文件的代码不正确。
获取输入流的代码
public String storeFile(MultipartFile multipartFile, String entity, Long id, String uploadType, boolean isDerive,String customName)
throws Exception
{
try
{
System.out.println(multipartFile.getSize());
String fileName = "";
String contentType = "";
if (multipartFile != null)
{
fileName = multipartFile.getOriginalFilename();
contentType = multipartFile.getContentType();
if (contentType == null)
{
contentType = "application/msword";
}
}
InputStream is = multipartFile.getInputStream();
String filePath = getFileName(entity, uploadType, id, fileName, isDerive,customName);
Helper.storeFile(is, filePath);
precedingPath = precedingPath.length() > 0 ? precedingPath + "/":"";
return precedingPath + filePath;
}
catch (WebException e)
{
e.printStackTrace();
throw e;
}
catch (Exception e)
{
e.printStackTrace();
throw new WebException(e.getMessage(), IHttpConstants.INTERNAL_SERVER_ERROR, e);
}
}
Helper.storeFile
public static File storeFile(InputStream is, String filePath) throws IOException {
try {
String staticRepoPath = null;
if (MasterData.getInstance().getSettingsMap().containsKey(Settings.REPO_LOCATION.toString())) {
staticRepoPath = MasterData.getInstance().getSettingsMap().get(Settings.REPO_LOCATION.toString());
} else {
throw new WebException("Invalid Settings");
}
byte[] buffer = new byte[is.available()];
is.read(buffer);
File targetFile = new File(staticRepoPath + File.separator + filePath);
@SuppressWarnings("resource")
OutputStream outStream = new FileOutputStream(targetFile);
outStream.write(buffer);
return targetFile;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
我的Ajax请求如下
var fd = new FormData();
//Take the first selected file
fd.append("file", document.actualFile);
//Generic AJAX call
CandidateService.ajax_uploadDocumentWithDocType($scope.candidate.id, fd, document.docType, function (error, json)
上传时的内容类型:
var config = {headers:{'X-Auth-Token':authToken, 'Content-Type': undefined}, transformRequest: angular.identity};
有人知道我该如何解决这个问题并成功上传文件吗?
Q1) 为什么请求调度器和处理文件数据的控制器之间的文件大小会发生变化。
Q2) 文件大小的这种变化是否是文件损坏的原因? Libre Office 导致常规 Input/Output 错误。
我发现了文件上传的问题。我在中间有一个 spring 过滤器,它正在将请求更改为 wrappedRequest。这是向多部分数据添加额外数据并导致文件损坏。
嗯,在我的例子中,我在通过亚马逊 API 网关访问 API 时遇到了完全相同的问题。结果我忘了在 API 网关上允许多部分 ContentType。 有点奇怪,请求仍然发送到我的服务器并且文本文件工作正常。