一、问题背景
使用 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的资料请关注代码网其它相关文章!
发表评论