Springファイルアップロードコンポーネント
15935 ワード
アップロードにFileUploadExceptionが現れます.Stream closed簡単な説明 シーン 原因分析 解決方法 拡張 簡単に述べる
プロジェクトでは、CommonsMultiiprtResoloverをファイルとして使用して、ファイル上の解像度をアップロードします.ブロックの中で権限検査といくつかのパラメータチェックを行います.フロントエンドがアップロードインターフェースを呼び出す過程で、フロントエンドパラメータが正しくないため、スクリーンは直接エラー情報を返しましたが、意外にもFileUploadException:Stream closedが異常です.
シーン
以下はフロントエンドにエラーメッセージを直接書き込むコードです.contentはエラーメッセージのjson列です.通常の場合、このようなIOフロー操作の書き方は全く問題ありません.
異常情報を分析すると、Commons MultiiprtResolaverのcleanultipad方法で異常発生し、コードの断片は以下の通りである.
解決方法
大雑把に探究したところ、レスリングの出力ストリームはオフにされているが、対応するRequestの入力ストリームは同時にオフにされていることがわかった.debugとTomcatのAPIから、RequestオブジェクトはTomcatによってFacadeモードで包装され、Requestオブジェクトには対応するResponse参照が含まれていることがわかる.RequestストリームはReponseフローをシャットダウンすることが証明されました.原因はTomcatの原理を結び付けて深く探究する必要があります.以下は改造後のコードです.
拡張
1、Spring MVCのアップロード解像器は2種類に分けられています.それぞれCommonsMultiiPad ResolaverとStanddardServletMultilertResolaverです.2、Standard ServletMultiResolaverはservlet 3.0に基づいて、MultiiprtResolaverの標準的な実現であり、Spring Bootのデフォルトのアップロードコンポーネントでもあります.Webプロジェクトには、web.xmlに影響が必要なservletにmultiipad-configを配置する必要がある.SpringBoot項目については、直接にappicationプロファイルに属性を配置したり、MultiiprtConfigElementをカスタマイズしたりすることができます.カスタムservletに対して、servlet classにMultiiprtConfig注釈を加えることもできます.3、CommonsMultiiprtResolaverはウェブプロジェクトでよく使われるアップロードコンポーネントであり、容器の中で定義する必要があります.
Spring Bootを例にして、構成を説明します.
プロジェクトでは、CommonsMultiiprtResoloverをファイルとして使用して、ファイル上の解像度をアップロードします.ブロックの中で権限検査といくつかのパラメータチェックを行います.フロントエンドがアップロードインターフェースを呼び出す過程で、フロントエンドパラメータが正しくないため、スクリーンは直接エラー情報を返しましたが、意外にもFileUploadException:Stream closedが異常です.
シーン
以下はフロントエンドにエラーメッセージを直接書き込むコードです.contentはエラーメッセージのjson列です.通常の場合、このようなIOフロー操作の書き方は全く問題ありません.
// response
public static void returnMessage(HttpServletResponse response, String content) {
response.setCharacterEncoding("UTF-8");
response.setContentType("application/json");
PrintWriter pWriter = null;
try {
pWriter = response.getWriter();
pWriter.write(content);
} catch (IOException e) {
logger.error("returnMessage", e);
} finally {
if (pWriter != null) {
pWriter.flush();
pWriter.close();
}
}
}
原因分析異常情報を分析すると、Commons MultiiprtResolaverのcleanultipad方法で異常発生し、コードの断片は以下の通りである.
public void cleanupMultipart(MultipartHttpServletRequest request) {
try {
cleanupFileItems(request.getMultiFileMap());
}
catch (Throwable ex) {
logger.warn("Failed to perform multipart cleanup for servlet request", ex);
}
}
request.get MultiFileMap()を呼び出したときに実行されるのはAbstractMultiiPad HttpServletRequest類のget Multifiles()です.この方法は怠惰なロード方法で、MultiiprtFile Mapが必要な時だけ呼び出します.要求はブロックでブロックされます.つまり、掃除時に初めて使用します.ここで初期化します.続いてパーrseRequest()解析要求を呼び出し、入力ストリームreadBoddData()を使用すると、ストリームが閉じられていることが分かり、異常が発生しました.解決方法
大雑把に探究したところ、レスリングの出力ストリームはオフにされているが、対応するRequestの入力ストリームは同時にオフにされていることがわかった.debugとTomcatのAPIから、RequestオブジェクトはTomcatによってFacadeモードで包装され、Requestオブジェクトには対応するResponse参照が含まれていることがわかる.RequestストリームはReponseフローをシャットダウンすることが証明されました.原因はTomcatの原理を結び付けて深く探究する必要があります.以下は改造後のコードです.
public void returnMessage(HttpServletRequest request, HttpServletResponse response, String content) {
response.setCharacterEncoding("UTF-8");
response.setContentType("application/json");
PrintWriter pWriter = null;
try {
pWriter = response.getWriter();
pWriter.write(content);
} catch (IOException e) {
log.error("returnMessage", e);
} finally {
if (!ServletFileUpload.isMultipartContent(request)) {
if (pWriter != null) {
pWriter.flush();
pWriter.close();
}
}
}
}
Springフレームでは手動でストリームを閉じないでください.システムに任せて自分で閉じます.拡張
1、Spring MVCのアップロード解像器は2種類に分けられています.それぞれCommonsMultiiPad ResolaverとStanddardServletMultilertResolaverです.2、Standard ServletMultiResolaverはservlet 3.0に基づいて、MultiiprtResolaverの標準的な実現であり、Spring Bootのデフォルトのアップロードコンポーネントでもあります.Webプロジェクトには、web.xmlに影響が必要なservletにmultiipad-configを配置する必要がある.SpringBoot項目については、直接にappicationプロファイルに属性を配置したり、MultiiprtConfigElementをカスタマイズしたりすることができます.カスタムservletに対して、servlet classにMultiiprtConfig注釈を加えることもできます.3、CommonsMultiiprtResolaverはウェブプロジェクトでよく使われるアップロードコンポーネントであり、容器の中で定義する必要があります.
Spring Bootを例にして、構成を説明します.
StandardServletMultipartResolver ( ):
1、 application.yml application.properties ,
spring.http.multipart.maxFileSize=10MB
spring.http.multipart.maxRequestSize=50MB
2、 MultipartConfigElement
@Bean
public MultipartConfigElement getMultipartElement() {
// MultipartConfigElement
MultipartConfigFactory factory = new MultipartConfigFactory();
// , ,
factory.setMaxFileSize("50MB");
//
factory.setMaxRequestSize("100MB");
MultipartConfigElement element = factory.createMultipartConfig();
return element;
}
CommonsMultipartResolver
@Bean
public CommonsMultipartResolver getMultipartResolver() {
CommonsMultipartResolver resolver = new CommonsMultipartResolver();
resolver.setMaxUploadSize(439426520l);
resolver.setResolveLazily(true);// ,
resolver.setDefaultEncoding("UTF-8");
return resolver;
}
そのXML設定方式は以下の通りです. <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<property name="resolveLazily" value="true" />
<!-- 10MB -->
<property name="maxUploadSize" value="10485760" />
<property name="defaultEncoding" value="UTF-8" />
</bean>