は、今の問題は、新しいJakartaStreamMultiPartRequestを使用することによって解決することができます。MultiPartRequest の新しい実装が追加された
Strutsのバージョン2.3.18 からのよう - JakartaStreamMultiPartRequest。 大きなファイルを扱う詳細はWW-3025を確認するために使用することができますが、簡単なセットstruts.xmlで
<constant name="struts.multipart.parser" value="jakarta-stream" />
は、それを使用して起動することができます。
連結JIRA本体から:任意のサイズ制限を超えた場合
、直ちに FileUploadBase.SizeLimitExceededException又は FileUploadBase.FileSizeLimitExceededExceptionがスローと の解析は、マルチパートリクエストは、リクエストパラメータを提供せずに終了する さらなる処理のために。
これは、基本的にどのWebアプリケーションでも のサイズ制限を上回って処理することを不可能にします。
私の提案では、リクエストの解析は常に リクエストパラメータを送信するように完了する必要があります。サイズ制限を超えたケース/例外は、後で取得するために が収集される可能性があります。 はFileItemにマップされ、 アプリケーションレベルのFileItemで検証されます。これにより、アップロードされたファイルが大きすぎる場合に、アップロード入力フィールドを と誤ってマークすることができます。
実際に私はそのためのパッチを作成しました(添付ファイルを参照)。このパッチを使用すると、 commons-fileuploadは、サイズが の場合には常に解析を完了し、完全な解析後には、検出された場合には 例外がスローされます。
とクリスクランフォードさんのコメント:私はStruts2のための新しいマルチパートパーサに取り組んでいます
私は JakartaStreamMultiPartRequestを呼び出しています。
このマルチパートパーサが、それはコモンズのFileUploadストリーミング APIを使用してではなく、ファイル アップロードAPIへのリクエストの最大サイズチェックを委任することを除いて、既存のジャカルタ マルチパートパーサと同じ振る舞い、それを避けるために内部的に行われます アップロードAPIの既存の問題は、ループの反復を破り、パラメータが失われています。
素晴らしい、おかげでみんな:)
旧答え
私はそれが
- 単一のファイル(または複数のファイルの異なる振る舞いが原因だと思います)が定義された最大サイズを超えている場合、INPUT rを使用して通常のプロセスの最後にリダイレクトされます
- 要求全体の最大サイズの違反は、セキュリティメカニズムであり、ファイルサイズのチェックのような機能ではないため、他の要素の解析を中断します(おそらく?)。
ファイルが最初に解析されたファイルがマルチパート要求サイズの制限を破る場合(it should depend on their order in the page)、他のフィールド(フォームフィールド)が読み出せなく、したがって入力結果と戻さないとき。 MultiPartRequestWrapperため
Struts2 uses the Jakarta implementation:
struts.multipart.parser
- このプロパティはMultiPartRequestを拡張するクラスに設定する必要があります。現在、フレームワークには、Jakarta FileUploadの実装が付属しています。
ソースコードは、Struts2公式サイトor here(Googleより高速)で見つけることができます。これは、マルチパートフォームを投稿するときに呼ばれているものです。
public void parse(HttpServletRequest request, String saveDir) throws IOException {
try {
setLocale(request);
processUpload(request, saveDir);
} catch (FileUploadBase.SizeLimitExceededException e) {
if (LOG.isWarnEnabled()) {
LOG.warn("Request exceeded size limit!", e);
}
String errorMessage = buildErrorMessage(e, new Object[]{e.getPermittedSize(), e.getActualSize()});
if (!errors.contains(errorMessage)) {
errors.add(errorMessage);
}
} catch (Exception e) {
if (LOG.isWarnEnabled()) {
LOG.warn("Unable to parse request", e);
}
String errorMessage = buildErrorMessage(e, new Object[]{});
if (!errors.contains(errorMessage)) {
errors.add(errorMessage);
}
}
}
ところ、それはサイクルマルチアイテム、ファイルやフォームフィールドの両方そして、これは次のとおりです。終了します
private void processUpload(HttpServletRequest request, String saveDir) throws FileUploadException, UnsupportedEncodingException {
for (FileItem item : parseRequest(request, saveDir)) {
if (LOG.isDebugEnabled()) {
LOG.debug("Found item " + item.getFieldName());
}
if (item.isFormField()) {
processNormalFormField(item, request.getCharacterEncoding());
} else {
processFileField(item);
}
}
}
をFileUploadBaseに、各項目のこの実装では:
FileItemStreamImpl(String pName, String pFieldName,
String pContentType, boolean pFormField,
long pContentLength) throws IOException {
name = pName;
fieldName = pFieldName;
contentType = pContentType;
formField = pFormField;
final ItemInputStream itemStream = multi.newInputStream();
InputStream istream = itemStream;
if (fileSizeMax != -1) {
if (pContentLength != -1
&& pContentLength > fileSizeMax) {
FileSizeLimitExceededException e =
new FileSizeLimitExceededException(
format("The field %s exceeds its maximum permitted size of %s bytes.",
fieldName, fileSizeMax),
pContentLength, fileSizeMax);
e.setFileName(pName);
e.setFieldName(pFieldName);
throw new FileUploadIOException(e);
}
istream = new LimitedInputStream(istream, fileSizeMax) {
@Override
protected void raiseError(long pSizeMax, long pCount)
throws IOException {
itemStream.close(true);
FileSizeLimitExceededException e =
new FileSizeLimitExceededException(
format("The field %s exceeds its maximum permitted size of %s bytes.",
fieldName, pSizeMax),
pCount, pSizeMax);
e.setFieldName(fieldName);
e.setFileName(name);
throw new FileUploadIOException(e);
}
};
}
stream = istream;
}
ご覧のとおり、ファイルサイズの上限と要求サイズの上限はかなり異なっています。
私は楽しいソースを見てきましたが、実際に何が起こっているのかを確認するためにMultiPartRequestWrapperをデバッグしようとすると、この仮定を確認(または修正)することができます。楽しい
あなたのスタック内の最後のインターセプタとして 'fileUpload'インターセプタを含むように任意の理由は? –
別の場所とは対照的に、またはまったく同じではありませんか?今はデフォルトのスタックなどになっていますか?それが価値あるものであれば、私はインターセプターの最初/中/最後/ etcを無駄にすることを試みました。 – fmpdmb
「defaultStack」のように、最初のものや中間のものとは対照的です。インターセプタの順序は重要です。 'fileUpload'は' defaultStack'にありますが 'basicStack'にはありません。 –