一、问题背景
使用 resttemplate 调用 dms 文件服务器 http 接口,出现 500 异常报错
二、问题描述
通过 clienthttprequestinterceptor 拦截器设置 contenttype 和 basicauth 后,调用dms 文件服务器 http 接口,出现 500 异常报错
三、相关代码
resttemplate 及自定义 clienthttprequestinterceptor bean 对象代码
@bean(name = "dmsresttemplate")
public resttemplate resttemplate(
@qualifier("dmsrequestinterceptor") clienthttprequestinterceptor dmsrequestinterceptor) {
resttemplate resttemplate = new resttemplate();
((allencompassingformhttpmessageconverter) resttemplate.getmessageconverters().get(4))
.setmultipartcharset(standardcharsets.utf_8);
resttemplate.getinterceptors().add(dmsrequestinterceptor);
resttemplate.seterrorhandler(new defaultresponseerrorhandler() {
@override
public boolean haserror(clienthttpresponse response) throws ioexception {
return super.haserror(response.getstatuscode())
&& !httpstatus.not_found.equals(response.getstatuscode());
}
@override
public void handleerror(clienthttpresponse response) throws ioexception {
super.handleerror(response);
}
});
return resttemplate;
}
@bean
public clienthttprequestinterceptor dmsrequestinterceptor(filestorageproperties filestorageproperties) {
string username = filestorageproperties.getdms().getusername();
string password = filestorageproperties.getdms().getpassword();
return (request, body, execution) -> {
httpheaders headers = request.getheaders();
mediatype type = mediatype.parsemediatype(mediatype.multipart_form_data_value);
headers.setcontenttype(type);
headers.setbasicauth(username, password, standardcharsets.utf_8);
return execution.execute(request, body);
};
}
文件上传代码
@override
public filestoragebo upload(string filepath) throws baseappexception {
logger.debug("dmsfilestorage upload by file path start.");
if (stringutils.isempty(filestorageproperties.getdms().getresturl())) {
logger.error("dms rest url config not exist!");
exceptionhandler.publish("epa-common-0010", exceptionhandler.buss_error);
}
file tempfile = new file(filepath);
filestoragebo result = new filestoragebo(tempfile);
multivaluemap<string, object> postparameters = new linkedmultivaluemap<>();
filesystemresource resource = new filesystemresource(tempfile.getabsolutepath());
postparameters.add("file", resource);
postparameters.add("shardingkey", "epa_" + getshardingkey());
httpentity<multivaluemap<string, object>> httpentity = new httpentity<>(postparameters);
try {
string dmsid = dmsresttemplate.postforobject(filestorageproperties.getdms().getresturl() + "/file",
httpentity, string.class);
result.setfileidentity(dmsid);
logger.debug("dmsfilestorage upload by file path end. dms id is {}", dmsid);
}
catch (restclientexception e) {
logger.error(e);
exceptionhandler.publish("epa-common-0011", exceptionhandler.buss_error, e.getlocalizedmessage());
}
return result;
}
四、问题原因
拦截器中设置 contenttype 为 multipart/form-data 时,无法自动生成 boundary 信息,导致无法根据该分隔符信息来解析请求体
在使用multipart/form-data格式发送http请求时,请求体的数据会被分割成多个部分,每个部分之间使用一个特定的分隔符(boundary)进行分隔。这个boundary是在content-type头部中指定的,用于告诉服务器如何识别每个部分的开始和结束。
当使用resttemplate发送multipart/form-data请求时,resttemplate会自动处理boundary的生成和添加到请求的content-type头部中。这样服务器就能够正确解析请求体中的各个部分。
使用resttemplate构建multipart/form-data请求时,只需设置正确的content-type为multipart/form-data,resttemplate会负责生成请求体的各个部分,并在content-type头部中添加正确的boundary信息。
不需要手动追加boundary到请求体中,resttemplate会在内部处理这一细节,确保请求能够正确地被服务器解析。
因此,使用resttemplate发送multipart/form-data请求时,只需设置正确的content-type为multipart/form-data,resttemplate会负责处理boundary的生成和添加,确保请求能够正确发送到服务器并被正确解析。
通常情况下,content-type的设置应该由发送请求的代码负责,而不是在clienthttprequestinterceptor中进行设置。clienthttprequestinterceptor主要用于在发送请求之前或之后对请求进行修改或处理,例如添加认证信息、日志记录、错误处理等。
五、问题修复
将 contenttype 移到上传代码中
拦截器 bean:
@bean
public clienthttprequestinterceptor dmsrequestinterceptor(filestorageproperties filestorageproperties) {
string username = filestorageproperties.getdms().getusername();
string password = filestorageproperties.getdms().getpassword();
return (request, body, execution) -> {
httpheaders headers = request.getheaders();
headers.setbasicauth(username, password, standardcharsets.utf_8);
return execution.execute(request, body);
};
}
上传代码:
@override
public filestoragebo upload(string filepath) throws baseappexception {
logger.debug("dmsfilestorage upload by file path start.");
if (stringutils.isempty(filestorageproperties.getdms().getresturl())) {
logger.error("dms rest url config not exist!");
exceptionhandler.publish("epa-common-0010", exceptionhandler.buss_error);
}
file tempfile = new file(filepath);
filestoragebo result = new filestoragebo(tempfile);
multivaluemap<string, object> postparameters = new linkedmultivaluemap<>();
filesystemresource resource = new filesystemresource(tempfile.getabsolutepath());
postparameters.add("file", resource);
postparameters.add("shardingkey", "epa_" + getshardingkey());
httpheaders headers = new httpheaders();
mediatype type = mediatype.parsemediatype(mediatype.multipart_form_data_value);
headers.setcontenttype(type);
httpentity<multivaluemap<string, object>> httpentity = new httpentity<>(postparameters, headers);
try {
string dmsid = dmsresttemplate.postforobject(filestorageproperties.getdms().getresturl() + "/file",
httpentity, string.class);
result.setfileidentity(dmsid);
logger.debug("dmsfilestorage upload by file path end. dms id is {}", dmsid);
}
catch (restclientexception e) {
logger.error(e);
exceptionhandler.publish("epa-common-0011", exceptionhandler.buss_error, e.getlocalizedmessage());
}
return result;
}
以上就是resttemplate上传文件500异常的原因及解决方法的详细内容,更多关于resttemplate上传文件500的资料请关注代码网其它相关文章!
发表评论