blob: ac2d1737305e0a3224e4430ff0816d8db80a0b12 [file] [log] [blame]
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8"/>
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
<meta name="Date-Revision-yyyymmdd" content="20140918"/>
<meta http-equiv="Content-Language" content="en"/>
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<title>Action File Upload</title>
<link href="//fonts.googleapis.com/css?family=Source+Sans+Pro:300,400,600,700,400italic,600italic,700italic" rel="stylesheet" type="text/css">
<link href="//netdna.bootstrapcdn.com/font-awesome/4.0.3/css/font-awesome.css" rel="stylesheet">
<link href="/css/main.css" rel="stylesheet">
<link href="/css/custom.css" rel="stylesheet">
<link href="/css/syntax.css" rel="stylesheet">
<script src="//code.jquery.com/jquery-1.11.0.min.js"></script>
<script type="text/javascript" src="/bootstrap/js/bootstrap.js"></script>
<script type="text/javascript" src="/js/community.js"></script>
<!-- Matomo -->
<script>
var _paq = window._paq = window._paq || [];
/* tracker methods like "setCustomDimension" should be called before "trackPageView" */
/* We explicitly disable cookie tracking to avoid privacy issues */
_paq.push(['disableCookies']);
_paq.push(['trackPageView']);
_paq.push(['enableLinkTracking']);
(function() {
var u="//analytics.apache.org/";
_paq.push(['setTrackerUrl', u+'matomo.php']);
_paq.push(['setSiteId', '41']);
var d=document, g=d.createElement('script'), s=d.getElementsByTagName('script')[0];
g.async=true; g.src=u+'matomo.js'; s.parentNode.insertBefore(g,s);
})();
</script>
<!-- End Matomo Code -->
</head>
<body>
<a href="https://github.com/apache/struts" class="github-ribbon">
<img decoding="async" loading="lazy" style="position: absolute; right: 0; border: 0;" width="149" height="149" src="https://github.blog/wp-content/uploads/2008/12/forkme_right_red_aa0000.png?resize=149%2C149" class="attachment-full size-full" alt="Fork me on GitHub" data-recalc-dims="1">
</a>
<header>
<nav>
<div role="navigation" class="navbar navbar-default navbar-fixed-top">
<div class="container">
<div class="navbar-header">
<button type="button" data-toggle="collapse" data-target="#struts-menu" class="navbar-toggle">
Menu
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a href="/index.html" class="navbar-brand logo"><img src="/img/struts-logo.svg"></a>
</div>
<div id="struts-menu" class="navbar-collapse collapse">
<ul class="nav navbar-nav">
<li class="dropdown">
<a data-toggle="dropdown" href="#" class="dropdown-toggle">
Home<b class="caret"></b>
</a>
<ul class="dropdown-menu">
<li><a href="/index.html">Welcome</a></li>
<li><a href="/download.cgi">Download</a></li>
<li><a href="/releases.html">Releases</a></li>
<li><a href="/announce-2024.html">Announcements</a></li>
<li><a href="http://www.apache.org/licenses/">License</a></li>
<li><a href="https://www.apache.org/foundation/thanks.html">Thanks!</a></li>
<li><a href="https://www.apache.org/foundation/sponsorship.html">Sponsorship</a></li>
<li><a href="https://privacy.apache.org/policies/privacy-policy-public.html">Privacy Policy</a></li>
</ul>
</li>
<li class="dropdown">
<a data-toggle="dropdown" href="#" class="dropdown-toggle">
Support<b class="caret"></b>
</a>
<ul class="dropdown-menu">
<li><a href="/mail.html">User Mailing List</a></li>
<li><a href="https://issues.apache.org/jira/browse/WW">Issue Tracker</a></li>
<li><a href="/security.html">Reporting Security Issues</a></li>
<li><a href="/commercial-support.html">Commercial Support</a></li>
<li class="divider"></li>
<li><a href="https://cwiki.apache.org/confluence/display/WW/Migration+Guide">Version Notes</a></li>
<li><a href="https://cwiki.apache.org/confluence/display/WW/Security+Bulletins">Security Bulletins</a></li>
<li class="divider"></li>
<li><a href="/maven/project-info.html">Maven Project Info</a></li>
<li><a href="/maven/struts2-core/dependencies.html">Struts Core Dependencies</a></li>
<li><a href="/maven/struts2-plugins/modules.html">Plugin Dependencies</a></li>
</ul>
</li>
<li class="dropdown">
<a data-toggle="dropdown" href="#" class="dropdown-toggle">
Documentation<b class="caret"></b>
</a>
<ul class="dropdown-menu">
<li><a href="/birdseye.html">Birds Eye</a></li>
<li><a href="/primer.html">Key Technologies</a></li>
<li><a href="/kickstart.html">Kickstart FAQ</a></li>
<li><a href="https://cwiki.apache.org/confluence/display/WW/Home">Wiki</a></li>
<li class="divider"></li>
<li><a href="/getting-started/">Getting Started</a></li>
<li><a href="/security/">Security Guide</a></li>
<li><a href="/core-developers/">Core Developers Guide</a></li>
<li><a href="/tag-developers/">Tag Developers Guide</a></li>
<li><a href="/maven-archetypes/">Maven Archetypes</a></li>
<li><a href="/plugins/">Plugins</a></li>
<li><a href="/maven/struts2-core/apidocs/index.html">Struts Core API</a></li>
<li><a href="/tag-developers/tag-reference.html">Tag reference</a></li>
<li><a href="https://cwiki.apache.org/confluence/display/WW/FAQs">FAQs</a></li>
<li><a href="http://cwiki.apache.org/S2PLUGINS/home.html">Plugin registry</a></li>
</ul>
</li>
<li class="dropdown">
<a data-toggle="dropdown" href="#" class="dropdown-toggle">
Contributing<b class="caret"></b>
</a>
<ul class="dropdown-menu">
<li><a href="/youatstruts.html">You at Struts</a></li>
<li><a href="/helping.html">How to Help FAQ</a></li>
<li><a href="/dev-mail.html">Development Lists</a></li>
<li class="divider"></li>
<li><a href="/submitting-patches.html">Submitting patches</a></li>
<li><a href="/builds.html">Source Code and Builds</a></li>
<li><a href="/coding-standards.html">Coding standards</a></li>
<li><a href="/contributors/">Contributors Guide</a></li>
<li class="divider"></li>
<li><a href="/release-guidelines.html">Release Guidelines</a></li>
<li><a href="/bylaws.html">PMC Charter</a></li>
<li><a href="/volunteers.html">Volunteers</a></li>
<li><a href="https://gitbox.apache.org/repos/asf?p=struts.git">Source Repository</a></li>
<li><a href="/updating-website.html">Updating the website</a></li>
</ul>
</li>
<li class="apache"><a href="http://www.apache.org/"><img src="/img/apache.png"></a></li>
</ul>
</div>
</div>
</div>
</nav>
</header>
<article class="container">
<section class="col-md-12">
<a class="edit-on-gh" href="https://github.com/apache/struts-site/edit/master/source/core-developers/action-file-upload.md" title="Edit this page on GitHub">Edit on GitHub</a>
<a href="action-file-upload-interceptor" title="back to Action File Upload Interceptor"><< back to Action File Upload Interceptor</a>
<h1 class="no_toc" id="action-file-upload">Action File Upload</h1>
<ul id="markdown-toc">
<li><a href="#dependencies" id="markdown-toc-dependencies">Dependencies</a></li>
<li><a href="#basic-usage" id="markdown-toc-basic-usage">Basic Usage</a> <ul>
<li><a href="#example-action-mapping" id="markdown-toc-example-action-mapping">Example action mapping:</a></li>
<li><a href="#example-jsp-form-tags" id="markdown-toc-example-jsp-form-tags">Example JSP form tags:</a></li>
</ul>
</li>
<li><a href="#uploading-multiple-files" id="markdown-toc-uploading-multiple-files">Uploading Multiple Files</a></li>
<li><a href="#advanced-configuration" id="markdown-toc-advanced-configuration">Advanced Configuration</a> <ul>
<li><a href="#files-number-limit" id="markdown-toc-files-number-limit">Files Number Limit</a></li>
<li><a href="#file-size-limits" id="markdown-toc-file-size-limits">File Size Limits</a></li>
<li><a href="#normal-field-size-limit" id="markdown-toc-normal-field-size-limit">Normal Field Size Limit</a></li>
<li><a href="#file-types" id="markdown-toc-file-types">File Types</a></li>
<li><a href="#error-messages" id="markdown-toc-error-messages">Error Messages</a></li>
<li><a href="#temporary-directories" id="markdown-toc-temporary-directories">Temporary Directories</a></li>
<li><a href="#alternate-libraries" id="markdown-toc-alternate-libraries">Alternate Libraries</a></li>
<li><a href="#request-validation" id="markdown-toc-request-validation">Request validation</a></li>
<li><a href="#disabling-file-upload-support" id="markdown-toc-disabling-file-upload-support">Disabling file upload support</a></li>
</ul>
</li>
</ul>
<p>The Struts 2 framework provides built-in support for processing file uploads that conform to <a href="http://www.ietf.org/rfc/rfc1867.txt">RFC 1867</a>,
“Form-based File Upload in HTML”. When correctly configured the framework will pass uploaded file(s) into your Action
class. Support for individual and multiple file uploads are provided. When a file is uploaded it will typically be
stored in a temporary directory. Uploaded files should be processed or moved by your Action class to ensure the data is
not lost. Be aware that servers may have a security policy in place that prohibits you from writing to directories other
than the temporary directory and the directories that belong to your web application.</p>
<h2 id="dependencies">Dependencies</h2>
<p>The Struts 2 framework leverages the Commons FileUpload library as a based library to support file upload in the framework.
The library is included in a base Struts 2 distribution.</p>
<h2 id="basic-usage">Basic Usage</h2>
<p>The <code class="language-plaintext highlighter-rouge">org.apache.struts2.interceptor.ActionFileUploadInterceptor</code> interceptor is included as part of the <code class="language-plaintext highlighter-rouge">defaultStack</code>
and named <code class="language-plaintext highlighter-rouge">actionFileUpload</code>. As long as the required libraries are added to your project you will be able to take
advantage of the Struts 2 file upload capability. Configure an Action mapping for your Action class as you typically would.</p>
<h3 id="example-action-mapping">Example action mapping:</h3>
<div class="language-xml highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt">&lt;action</span> <span class="na">name=</span><span class="s">"doUpload"</span> <span class="na">class=</span><span class="s">"com.example.UploadAction"</span><span class="nt">&gt;</span>
<span class="nt">&lt;result</span> <span class="na">name=</span><span class="s">"success"</span><span class="nt">&gt;</span>good_result.jsp<span class="nt">&lt;/result&gt;</span>
<span class="nt">&lt;/action&gt;</span>
</code></pre></div></div>
<p>A form must be created with a form field of type file, <code class="language-plaintext highlighter-rouge">&lt;INPUT type="file" name="upload"&gt;</code>. The form used to upload the
file must have its encoding type set to <code class="language-plaintext highlighter-rouge">multipart/form-data</code>, <code class="language-plaintext highlighter-rouge">&lt;form action="doUpload" enctype="multipart/form-data" method="post"&gt;</code>.
The standard procedure for adding these elements is by using the Struts 2 tag libraries as shown in the following
example:</p>
<h3 id="example-jsp-form-tags">Example JSP form tags:</h3>
<div class="language-xml highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt">&lt;s:form</span> <span class="na">action=</span><span class="s">"doUpload"</span> <span class="na">method=</span><span class="s">"post"</span> <span class="na">enctype=</span><span class="s">"multipart/form-data"</span><span class="nt">&gt;</span>
<span class="nt">&lt;s:file</span> <span class="na">name=</span><span class="s">"upload"</span> <span class="na">label=</span><span class="s">"File"</span><span class="nt">/&gt;</span>
<span class="nt">&lt;s:submit/&gt;</span>
<span class="nt">&lt;/s:form&gt;</span>
</code></pre></div></div>
<p>The <strong>actionFileUpload</strong> interceptor will use a dedicated interface <code class="language-plaintext highlighter-rouge">org.apache.struts2.action.UploadedFilesAware</code>
to transfer information and content of uploaded file. Your action should implement the interface to receive the uploaded file:</p>
<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">public</span> <span class="kd">class</span> <span class="nc">UploadAction</span> <span class="kd">extends</span> <span class="nc">ActionSupport</span> <span class="kd">implements</span> <span class="nc">UploadedFilesAware</span> <span class="o">{</span>
<span class="kd">private</span> <span class="nc">UploadedFile</span> <span class="n">uploadedFile</span><span class="o">;</span>
<span class="kd">private</span> <span class="nc">String</span> <span class="n">contentType</span><span class="o">;</span>
<span class="kd">private</span> <span class="nc">String</span> <span class="n">fileName</span><span class="o">;</span>
<span class="kd">private</span> <span class="nc">String</span> <span class="n">originalName</span><span class="o">;</span>
<span class="nd">@Override</span>
<span class="kd">public</span> <span class="kt">void</span> <span class="nf">withUploadedFiles</span><span class="o">(</span><span class="nc">List</span><span class="o">&lt;</span><span class="nc">UploadedFile</span><span class="o">&gt;</span> <span class="n">uploadedFiles</span><span class="o">)</span> <span class="o">{</span>
<span class="k">if</span> <span class="o">(!</span><span class="n">uploadedFiles</span><span class="o">.</span><span class="na">isEmpty</span><span class="o">())</span> <span class="o">{</span>
<span class="k">this</span><span class="o">.</span><span class="na">uploadedFile</span> <span class="o">=</span> <span class="n">uploadedFiles</span><span class="o">.</span><span class="na">get</span><span class="o">(</span><span class="mi">0</span><span class="o">);</span>
<span class="k">this</span><span class="o">.</span><span class="na">fileName</span> <span class="o">=</span> <span class="n">uploadedFile</span><span class="o">.</span><span class="na">getName</span><span class="o">();</span>
<span class="k">this</span><span class="o">.</span><span class="na">contentType</span> <span class="o">=</span> <span class="n">uploadedFile</span><span class="o">.</span><span class="na">getContentType</span><span class="o">();</span>
<span class="k">this</span><span class="o">.</span><span class="na">originalName</span> <span class="o">=</span> <span class="n">uploadedFile</span><span class="o">.</span><span class="na">getOriginalName</span><span class="o">();</span>
<span class="o">}</span>
<span class="o">}</span>
<span class="kd">public</span> <span class="nc">String</span> <span class="nf">execute</span><span class="o">()</span> <span class="o">{</span>
<span class="c1">// do something with the file</span>
<span class="k">return</span> <span class="no">SUCCESS</span><span class="o">;</span>
<span class="o">}</span>
<span class="o">}</span>
</code></pre></div></div>
<h2 id="uploading-multiple-files">Uploading Multiple Files</h2>
<p>As mentioned in the previous section one technique for uploading multiple files would be to simply have multiple form
input elements of type file all with different names. This would require a number of setter methods that was equal to 3
times the number of files being uploaded. Another option is to use Arrays or java.util.Lists. The following examples are
taken from the Showcase example application that is part sample applications you can download at <a href="http://struts.apache.org/download.cgi">download</a>.
For the Action mapping details see <code class="language-plaintext highlighter-rouge">struts-fileupload.xml</code> in the sample application download.</p>
<p><code class="language-plaintext highlighter-rouge">multipleUploadUsingList.jsp</code> Notice all file input types have the same name.</p>
<div class="language-html highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt">&lt;s:form</span> <span class="na">action=</span><span class="s">"multipleFileUploadUsingList"</span> <span class="na">method=</span><span class="s">"POST"</span> <span class="na">enctype=</span><span class="s">"multipart/form-data"</span><span class="nt">&gt;</span>
<span class="nt">&lt;s:file</span> <span class="na">label=</span><span class="s">"File (1)"</span> <span class="na">name=</span><span class="s">"upload"</span><span class="nt">/&gt;</span>
<span class="nt">&lt;s:file</span> <span class="na">label=</span><span class="s">"File (2)"</span> <span class="na">name=</span><span class="s">"upload"</span><span class="nt">/&gt;</span>
<span class="nt">&lt;s:file</span> <span class="na">label=</span><span class="s">"FIle (3)"</span> <span class="na">name=</span><span class="s">"upload"</span><span class="nt">/&gt;</span>
<span class="nt">&lt;s:submit</span> <span class="na">cssClass=</span><span class="s">"btn btn-primary"</span><span class="nt">/&gt;</span>
<span class="nt">&lt;/s:form&gt;</span>
</code></pre></div></div>
<p>The <code class="language-plaintext highlighter-rouge">org.apache.struts2.action.UploadedFilesAware</code> interface already supports uploading multiple files:</p>
<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">public</span> <span class="kd">class</span> <span class="nc">MultipleFileUploadUsingListAction</span> <span class="kd">extends</span> <span class="nc">ActionSupport</span> <span class="kd">implements</span> <span class="nc">UploadedFilesAware</span> <span class="o">{</span>
<span class="kd">private</span> <span class="nc">List</span><span class="o">&lt;</span><span class="nc">UploadedFile</span><span class="o">&gt;</span> <span class="n">uploads</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">ArrayList</span><span class="o">&lt;&gt;();</span>
<span class="kd">public</span> <span class="nc">List</span><span class="o">&lt;</span><span class="nc">UploadedFile</span><span class="o">&gt;</span> <span class="nf">getUpload</span><span class="o">()</span> <span class="o">{</span>
<span class="k">return</span> <span class="k">this</span><span class="o">.</span><span class="na">uploads</span><span class="o">;</span>
<span class="o">}</span>
<span class="nd">@Override</span>
<span class="kd">public</span> <span class="kt">void</span> <span class="nf">withUploadedFiles</span><span class="o">(</span><span class="nc">List</span><span class="o">&lt;</span><span class="nc">UploadedFile</span><span class="o">&gt;</span> <span class="n">uploads</span><span class="o">)</span> <span class="o">{</span>
<span class="k">this</span><span class="o">.</span><span class="na">uploads</span> <span class="o">=</span> <span class="n">uploads</span><span class="o">;</span>
<span class="o">}</span>
<span class="kd">private</span> <span class="nc">List</span><span class="o">&lt;</span><span class="nc">String</span><span class="o">&gt;</span> <span class="nf">getUploadFileNames</span><span class="o">()</span> <span class="o">{</span>
<span class="k">return</span> <span class="k">this</span><span class="o">.</span><span class="na">uploads</span><span class="o">.</span><span class="na">stream</span><span class="o">()</span>
<span class="o">.</span><span class="na">map</span><span class="o">(</span><span class="nl">UploadedFile:</span><span class="o">:</span><span class="n">getOriginalName</span><span class="o">)</span>
<span class="o">.</span><span class="na">collect</span><span class="o">(</span><span class="nc">Collectors</span><span class="o">.</span><span class="na">toList</span><span class="o">());</span>
<span class="o">}</span>
<span class="kd">private</span> <span class="nc">List</span><span class="o">&lt;</span><span class="nc">String</span><span class="o">&gt;</span> <span class="nf">getUploadContentTypes</span><span class="o">()</span> <span class="o">{</span>
<span class="k">return</span> <span class="k">this</span><span class="o">.</span><span class="na">uploads</span><span class="o">.</span><span class="na">stream</span><span class="o">()</span>
<span class="o">.</span><span class="na">map</span><span class="o">(</span><span class="nl">UploadedFile:</span><span class="o">:</span><span class="n">getContentType</span><span class="o">)</span>
<span class="o">.</span><span class="na">collect</span><span class="o">(</span><span class="nc">Collectors</span><span class="o">.</span><span class="na">toList</span><span class="o">());</span>
<span class="o">}</span>
<span class="kd">public</span> <span class="nc">String</span> <span class="nf">execute</span><span class="o">()</span> <span class="kd">throws</span> <span class="nc">Exception</span> <span class="o">{</span>
<span class="nc">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">println</span><span class="o">(</span><span class="s">"files:"</span><span class="o">);</span>
<span class="k">for</span> <span class="o">(</span><span class="nc">UploadedFile</span> <span class="n">u</span> <span class="o">:</span> <span class="n">uploads</span><span class="o">)</span> <span class="o">{</span>
<span class="nc">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">println</span><span class="o">(</span><span class="s">"*** "</span> <span class="o">+</span> <span class="n">u</span> <span class="o">+</span> <span class="s">"\t"</span> <span class="o">+</span> <span class="n">u</span><span class="o">.</span><span class="na">length</span><span class="o">());</span>
<span class="o">}</span>
<span class="nc">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">println</span><span class="o">(</span><span class="s">"filenames:"</span><span class="o">);</span>
<span class="k">for</span> <span class="o">(</span><span class="nc">String</span> <span class="n">n</span> <span class="o">:</span> <span class="n">getUploadFileNames</span><span class="o">())</span> <span class="o">{</span>
<span class="nc">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">println</span><span class="o">(</span><span class="s">"*** "</span> <span class="o">+</span> <span class="n">n</span><span class="o">);</span>
<span class="o">}</span>
<span class="nc">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">println</span><span class="o">(</span><span class="s">"content types:"</span><span class="o">);</span>
<span class="k">for</span> <span class="o">(</span><span class="nc">String</span> <span class="n">c</span> <span class="o">:</span> <span class="n">getUploadContentTypes</span><span class="o">())</span> <span class="o">{</span>
<span class="nc">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">println</span><span class="o">(</span><span class="s">"*** "</span> <span class="o">+</span> <span class="n">c</span><span class="o">);</span>
<span class="o">}</span>
<span class="nc">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">println</span><span class="o">(</span><span class="s">"\n\n"</span><span class="o">);</span>
<span class="k">return</span> <span class="no">SUCCESS</span><span class="o">;</span>
<span class="o">}</span>
<span class="o">}</span>
</code></pre></div></div>
<h2 id="advanced-configuration">Advanced Configuration</h2>
<p>The Struts 2 <code class="language-plaintext highlighter-rouge">default.properties</code> file defines several settings that affect the behavior of file uploading. You may find
it necessary to change these values. The names and default values are:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>struts.multipart.parser=jakarta
struts.multipart.saveDir= # Filesystem location to save parsed request data
struts.multipart.maxSize=2097152 # Max combined size of files per request
struts.multipart.maxFiles=256 # Max number of files per request
struts.multipart.maxFileSize= # Max size per file per request
struts.multipart.maxStringLength=4096 # Max length of a string parameter (a normal field) in a multipart request (since Struts 6.1.2.1)
</code></pre></div></div>
<p>You can also set the max options to unlimited by setting their value to <code class="language-plaintext highlighter-rouge">-1</code>, but please see the sections below for
further details on these options first.</p>
<h3 id="files-number-limit">Files Number Limit</h3>
<p>Since Struts 6.1.2 a new option was added, which uses Commons FileUpload feature to limit how many files can be
uploaded at once, in one request. This option requires to use Commons FileUpload ver. 1.5 at least and by default is set
to <strong>256</strong>. Please always set this to a finite value to prevent DoS attacks.</p>
<p>To change this value define a constant in <code class="language-plaintext highlighter-rouge">struts.xml</code> as follows:</p>
<div class="language-xml highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt">&lt;struts&gt;</span>
<span class="nt">&lt;constant</span> <span class="na">name=</span><span class="s">"struts.multipart.maxFiles"</span> <span class="na">value=</span><span class="s">"500"</span><span class="nt">/&gt;</span>
<span class="nt">&lt;/struts&gt;</span>
</code></pre></div></div>
<h3 id="file-size-limits">File Size Limits</h3>
<p>There are multiple methods to enforce file size limits.</p>
<p>There is <code class="language-plaintext highlighter-rouge">struts.multipart.maxSize</code> which is loaded from the Struts configuration. This setting exists for security
reasons to prohibit a malicious user from uploading extremely large files to fill up your server’s disk space. This
setting defaults to approximately 2MB and should be adjusted to the maximum size (2GB) that you expect to parse. If you
are uploading more than one file in a single request, the <code class="language-plaintext highlighter-rouge">struts.multipart.maxSize</code> applies to the combined total, not
the individual files.</p>
<p>There is also <code class="language-plaintext highlighter-rouge">struts.multipart.maxFileSize</code> which is not enforced by default, but can be enabled to enforce a max size
on a per-file basis.</p>
<p>The other setting, <code class="language-plaintext highlighter-rouge">maximumSize</code>, is an interceptor setting that is used to ensure a particular Action does not receive
a file that is too large. Note that the aforementioned settings are applied at the request parsing level and take
precedence over this interceptor setting.</p>
<p>Notice the locations of these settings in the following example:</p>
<div class="language-xml highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt">&lt;struts&gt;</span>
<span class="nt">&lt;constant</span> <span class="na">name=</span><span class="s">"struts.multipart.maxSize"</span> <span class="na">value=</span><span class="s">"1000000"</span><span class="nt">/&gt;</span>
<span class="nt">&lt;constant</span> <span class="na">name=</span><span class="s">"struts.multipart.maxFileSize"</span> <span class="na">value=</span><span class="s">"750000"</span><span class="nt">/&gt;</span>
<span class="nt">&lt;action</span> <span class="na">name=</span><span class="s">"doUpload"</span> <span class="na">class=</span><span class="s">"com.example.UploadAction"</span><span class="nt">&gt;</span>
<span class="nt">&lt;interceptor-ref</span> <span class="na">name=</span><span class="s">"basicStack"</span><span class="nt">/&gt;</span>
<span class="nt">&lt;interceptor-ref</span> <span class="na">name=</span><span class="s">"fileUpload"</span><span class="nt">&gt;</span>
<span class="nt">&lt;param</span> <span class="na">name=</span><span class="s">"maximumSize"</span><span class="nt">&gt;</span>500000<span class="nt">&lt;/param&gt;</span>
<span class="nt">&lt;/interceptor-ref&gt;</span>
<span class="nt">&lt;interceptor-ref</span> <span class="na">name=</span><span class="s">"validation"</span><span class="nt">/&gt;</span>
<span class="nt">&lt;interceptor-ref</span> <span class="na">name=</span><span class="s">"workflow"</span><span class="nt">/&gt;</span>
<span class="nt">&lt;result</span> <span class="na">name=</span><span class="s">"success"</span><span class="nt">&gt;</span>good_result.jsp<span class="nt">&lt;/result&gt;</span>
<span class="nt">&lt;/action&gt;</span>
<span class="nt">&lt;/struts&gt;</span>
</code></pre></div></div>
<h3 id="normal-field-size-limit">Normal Field Size Limit</h3>
<p>Since Struts 6.1.2.1 a new option has been introduced to limit the size of a normal string field in the multipart request.
The default limit is set to 4096 bytes:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>struts.multipart.maxStringLength=4096
</code></pre></div></div>
<p>This options prevents attacks, which consists of multiple large objects in the multipart request. Such attack can exhaust
the available memory and finally produce <code class="language-plaintext highlighter-rouge">OutOfMemoryException</code>. If the limit is too low you can increase it by defining
the following constant in <code class="language-plaintext highlighter-rouge">struts.xml</code>:</p>
<div class="language-xml highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt">&lt;struts&gt;</span>
<span class="nt">&lt;constant</span> <span class="na">name=</span><span class="s">"struts.multipart.maxStringLength"</span> <span class="na">value=</span><span class="s">"10000"</span><span class="nt">/&gt;</span>
<span class="nt">&lt;action</span> <span class="na">name=</span><span class="s">"doUpload"</span> <span class="na">class=</span><span class="s">"com.example.UploadAction"</span><span class="nt">&gt;</span>
...
<span class="nt">&lt;/action&gt;</span>
<span class="nt">&lt;/struts&gt;</span>
</code></pre></div></div>
<h3 id="file-types">File Types</h3>
<p>There are two ways to limit the uploaded file type, decoratively and programmatically. To decoratively limit the file
type a comma separated list of allowedTypes can be specified as a fileUpload interceptor param as shown in the following
example:</p>
<div class="language-xml highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt">&lt;action</span> <span class="na">name=</span><span class="s">"doUpload"</span> <span class="na">class=</span><span class="s">"com.example.UploadAction"</span><span class="nt">&gt;</span>
<span class="nt">&lt;interceptor-ref</span> <span class="na">name=</span><span class="s">"basicStack"</span><span class="nt">/&gt;</span>
<span class="nt">&lt;interceptor-ref</span> <span class="na">name=</span><span class="s">"fileUpload"</span><span class="nt">&gt;</span>
<span class="nt">&lt;param</span> <span class="na">name=</span><span class="s">"allowedTypes"</span><span class="nt">&gt;</span>image/jpeg,image/gif<span class="nt">&lt;/param&gt;</span>
<span class="nt">&lt;/interceptor-ref&gt;</span>
<span class="nt">&lt;interceptor-ref</span> <span class="na">name=</span><span class="s">"validation"</span><span class="nt">/&gt;</span>
<span class="nt">&lt;interceptor-ref</span> <span class="na">name=</span><span class="s">"workflow"</span><span class="nt">/&gt;</span>
<span class="nt">&lt;result</span> <span class="na">name=</span><span class="s">"success"</span><span class="nt">&gt;</span>good_result.jsp<span class="nt">&lt;/result&gt;</span>
<span class="nt">&lt;/action&gt;</span>
</code></pre></div></div>
<p>When the uploaded file type does not match one of the MIME types specified a field error will be created as described in
the next section entitled Error Messages. Programmatically limiting the file type means using the information passed in
to your Action class via the <code class="language-plaintext highlighter-rouge">setXContentType(String contentType)</code> method. The benefit to this type of approach would be
that it’s more flexible and no interceptor configuration would be needed if file sizes are keep under 2 megs.</p>
<h3 id="error-messages">Error Messages</h3>
<p>If an error occurs several field errors will be added assuming that the action
implements <code class="language-plaintext highlighter-rouge">com.opensymphony.xwork2.ValidationAware</code>
or extends <code class="language-plaintext highlighter-rouge">com.opensymphony.xwork2.ActionSupport</code>. These error messages are based on several i18n values stored in
struts-messages.properties, a default i18n file processed for all i18n requests. You can override the text of these
messages by providing text for the following keys:</p>
<table>
<thead>
<tr>
<th>Error Key</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td><code class="language-plaintext highlighter-rouge">struts.messages.error.uploading</code></td>
<td>A general error that occurs when the file could not be uploaded</td>
</tr>
<tr>
<td><code class="language-plaintext highlighter-rouge">struts.messages.error.file.too.large</code></td>
<td>Occurs when the uploaded file is too large as specified by maximumSize.</td>
</tr>
<tr>
<td><code class="language-plaintext highlighter-rouge">struts.messages.error.content.type.not.allowed</code></td>
<td>Occurs when the uploaded file does not match the expected content types specified</td>
</tr>
<tr>
<td><code class="language-plaintext highlighter-rouge">struts.messages.error.file.extension.not.allowed</code></td>
<td>Occurs when uploaded file has disallowed extension</td>
</tr>
<tr>
<td><code class="language-plaintext highlighter-rouge">struts.messages.upload.error.SizeLimitExceededException</code></td>
<td>Occurs when the upload request (as a whole) exceed configured <strong>struts.multipart.maxSize</strong></td>
</tr>
<tr>
<td><code class="language-plaintext highlighter-rouge">struts.messages.upload.error.FileSizeLimitExceededException</code></td>
<td>Occurs when a file within the upload request exceeds configured <strong>struts.multipart.maxFileSize</strong></td>
</tr>
<tr>
<td><code class="language-plaintext highlighter-rouge">struts.messages.upload.error.FileCountLimitExceededException</code></td>
<td>Occurs when the number of files in the upload request exceeds configured <strong>struts.multipart.maxFiles</strong></td>
</tr>
<tr>
<td><code class="language-plaintext highlighter-rouge">struts.messages.upload.error.&lt;Exception class SimpleName&gt;</code></td>
<td>Occurs when any other exception took place during file upload process</td>
</tr>
</tbody>
</table>
<h3 id="temporary-directories">Temporary Directories</h3>
<p>All uploaded files are saved to a temporary directory by the framework before being passed in to an Action. Depending on
the allowed file sizes it may be necessary to have the framework store these temporary files in an alternate location.
To do this change <code class="language-plaintext highlighter-rouge">struts.multipart.saveDir</code>
to the directory where the uploaded files will be placed. If this property is not set it defaults
to <code class="language-plaintext highlighter-rouge">javax.servlet.context.tempdir</code>. Keep in mind that on some operating systems, like Solaris, <code class="language-plaintext highlighter-rouge">/tmp</code> is memory based
and files stored in that directory would consume an amount of RAM approximately equal to the size of the uploaded file.</p>
<h3 id="alternate-libraries">Alternate Libraries</h3>
<p>The <code class="language-plaintext highlighter-rouge">struts.multipart.parser</code> used by the fileUpload interceptor to handle HTTP POST requests, encoded using the
MIME-type <code class="language-plaintext highlighter-rouge">multipart/form-data</code>, can be changed out. Currently there are two choices, jakarta and pell. The jakarta
parser is a standard part of the Struts 2 framework needing only its required libraries added to a project. The pell
parser uses Jason Pell’s multipart parser instead of the Commons-FileUpload library. The pell parser is a Struts 2
plugin, for more details see: <a href="../plugins/pell/">Pell multipart plugin</a>. There was a third alternative, cos, but it was
removed due to licensing incompatibilities.</p>
<p>As from Struts version 2.3.18 a new implementation of <code class="language-plaintext highlighter-rouge">MultiPartRequest</code> was added - <code class="language-plaintext highlighter-rouge">JakartaStreamMultiPartRequest</code>. It
can be used to handle large files, see <a href="https://issues.apache.org/jira/browse/WW-3025">WW-3025</a> for more details, but
you can simple set</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>&lt;constant name="struts.multipart.parser" value="jakarta-stream" /&gt;
</code></pre></div></div>
<p>in struts.xml to start using it.</p>
<h3 id="request-validation">Request validation</h3>
<p>The <code class="language-plaintext highlighter-rouge">struts.multipart.validationRegex</code> is used to define a RegEx to be used to validate if the incoming request is a
multipart request. The request must use the <code class="language-plaintext highlighter-rouge">POST</code> method and match the RegEx, by default the RegEx is defined as
follow:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>^multipart/form-data(?:\\s*;\\s*boundary=[0-9a-zA-Z'()+_,\\-./:=?]{1,70})?(?:\\s*;\\s*charset=[a-zA-Z\\-0-9]{3,14})?
</code></pre></div></div>
<p>Please read <a href="https://www.w3.org/Protocols/rfc1341/7_2_Multipart.html">RFC1341</a> the <strong>Multipart section</strong> for more details, existing Struts <code class="language-plaintext highlighter-rouge">Multipart</code> parsers support
only <code class="language-plaintext highlighter-rouge">multipart/form-data</code> content type. This option is available since Struts 2.3.11.</p>
<h3 id="disabling-file-upload-support">Disabling file upload support</h3>
<p>You can alternatively disable the whole file upload mechanism defining a constant in <code class="language-plaintext highlighter-rouge">struts.xml</code>:</p>
<div class="language-xml highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt">&lt;constant</span> <span class="na">name=</span><span class="s">"struts.multipart.enabled"</span> <span class="na">value=</span><span class="s">"false"</span><span class="nt">/&gt;</span>
</code></pre></div></div>
<p>With this constant in place, Struts will ignore a <code class="language-plaintext highlighter-rouge">Content-Type</code> header and will treat each request as an ordinary http
request. This option is available since Struts 2.3.11.</p>
</section>
</article>
<footer class="container">
<div class="col-md-12">
Copyright &copy; 2000-2022 <a href="https://www.apache.org/">The Apache Software Foundation</a>.
Apache Struts, Struts, Apache, the Apache feather logo, and the Apache Struts project logos are
trademarks of The Apache Software Foundation. All Rights Reserved.
</div>
<div class="col-md-12">Logo and website design donated by <a href="https://softwaremill.com/">SoftwareMill</a>.</div>
</footer>
<script>!function (d, s, id) {
var js, fjs = d.getElementsByTagName(s)[0];
if (!d.getElementById(id)) {
js = d.createElement(s);
js.id = id;
js.src = "//platform.twitter.com/widgets.js";
fjs.parentNode.insertBefore(js, fjs);
}
}(document, "script", "twitter-wjs");</script>
<script src="https://apis.google.com/js/platform.js" async="async" defer="defer"></script>
<div id="fb-root"></div>
<script>(function (d, s, id) {
var js, fjs = d.getElementsByTagName(s)[0];
if (d.getElementById(id)) return;
js = d.createElement(s);
js.id = id;
js.src = "//connect.facebook.net/en_GB/all.js#xfbml=1";
fjs.parentNode.insertBefore(js, fjs);
}(document, 'script', 'facebook-jssdk'));</script>
</body>
</html>