File: using.xml

package info (click to toggle)
libcommons-fileupload-java 1.2.1-1
  • links: PTS, VCS
  • area: main
  • in suites: lenny
  • size: 752 kB
  • ctags: 654
  • sloc: java: 3,652; xml: 2,209; makefile: 13
file content (442 lines) | stat: -rw-r--r-- 18,464 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
<?xml version="1.0"?>
<!--
 Licensed to the Apache Software Foundation (ASF) under one or more
 contributor license agreements.  See the NOTICE file distributed with
 this work for additional information regarding copyright ownership.
 The ASF licenses this file to You under the Apache License, Version 2.0
 (the "License"); you may not use this file except in compliance with
 the License.  You may obtain a copy of the License at

      http://www.apache.org/licenses/LICENSE-2.0

 Unless required by applicable law or agreed to in writing, software
 distributed under the License is distributed on an "AS IS" BASIS,
 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 See the License for the specific language governing permissions and
 limitations under the License.
-->

<document>

  <properties>
    <title>Using FileUpload</title>
    <author email="martinc@apache.org">Martin Cooper</author>
  </properties>

<body>

  <section name="Using FileUpload">
    <p>
      FileUpload can be used in a number of different ways, depending upon the
      requirements of your application. In the simplest case, you will call a
      single method to parse the servlet request, and then process the list of
      items as they apply to your application. At the other end of the scale,
      you might decide to customize FileUpload to take full control of the way
      in which individual items are stored; for example, you might decide to
      stream the content into a database.
    </p>
    <p>
      Here, we will describe the basic principles of FileUpload, and illustrate
      some of the simpler - and most common - usage patterns. Customization of
      FileUpload is described <a href="customizing.html">elsewhere</a>.
    </p>
    <p>
       FileUpload depends on Commons IO, so make sure you have the version 
       mentioned on the <a href="dependencies.html">dependencies page</a> in 
       your classpath before continuing.
    </p>
  </section>

  <section name="How it works">
    <p>
      A file upload request comprises an ordered list of <em>items</em> that
      are encoded according to
      <a href="http://www.ietf.org/rfc/rfc1867.txt">RFC 1867</a>,
      "Form-based File Upload in HTML". FileUpload can parse such a request
      and provide your application with a list of the individual uploaded
      items. Each such item implements the <code>FileItem</code> interface,
      regardless of its underlying implementation.
    </p>
    <p>
      This page describes the traditional API of the commons fileupload
      library. The traditional API is a convenient approach. However, for
      ultimate performance, you might prefer the faster
      <a href="streaming.html">Streaming API</a>.
    </p>
    <p>
      Each file item has a number of properties that might be of interest for
      your application. For example, every item has a name and a content type,
      and can provide an <code>InputStream</code> to access its data. On the
      other hand, you may need to process items differently, depending upon
      whether the item is a regular form field - that is, the data came from
      an ordinary text box or similar HTML field - or an uploaded file. The
      <code>FileItem</code> interface provides the methods to make such a
      determination, and to access the data in the most appropriate manner.
    </p>
    <p>
      FileUpload creates new file items using a <code>FileItemFactory</code>.
      This is what gives FileUpload most of its flexibility. The factory has
      ultimate control over how each item is created. The factory implementation
      that currently ships with FileUpload stores the item's data in memory or
      on disk, depending on the size of the item (i.e. bytes of data). However,
      this behavior can be customized to suit your application.
    </p>
  </section>

  <section name="Servlets and Portlets">
    <p>
      Starting with version 1.1, FileUpload supports file upload requests in
      both servlet and portlet environments. The usage is almost identical in
      the two environments, so the remainder of this document refers only to
      the servlet environment.
    </p>
    <p>
      If you are building a portlet application, the following are the two
      distinctions you should make as you read this document:
      <ul>
        <li>
          Where you see references to the <code>ServletFileUpload</code> class,
          substitute the <code>PortletFileUpload</code> class.
        </li>
        <li>
          Where you see references to the <code>HttpServletRequest</code> class,
          substitute the <code>ActionRequest</code> class.
        </li>
      </ul>
    </p>
  </section>

  <section name="Parsing the request">
    <p>
      Before you can work with the uploaded items, of course, you need to parse
      the request itself. Ensuring that the request is actually a file upload
      request is straightforward, but FileUpload makes it simplicity itself, by
      providing a static method to do just that.
    </p>
<source><![CDATA[// Check that we have a file upload request
boolean isMultipart = ServletFileUpload.isMultipartContent(request);]]></source>
      <p>
        Now we are ready to parse the request into its constituent items.
      </p>
    <subsection name="The simplest case">
      <p>
        The simplest usage scenario is the following:
        <ul>
          <li>
            Uploaded items should be retained in memory as long as they are
            reasonably small.
          </li>
          <li>
            Larger items should be written to a temporary file on disk.
          </li>
          <li>
            Very large upload requests should not be permitted.
          </li>
          <li>
            The built-in defaults for the maximum size of an item to
            be retained in memory, the maximum permitted size of an upload
            request, and the location of temporary files are acceptable.
          </li>
        </ul>
      </p>
      <p>
        Handling a request in this scenario couldn't be much simpler:
      </p>
<source><![CDATA[// Create a factory for disk-based file items
FileItemFactory factory = new DiskFileItemFactory();

// Create a new file upload handler
ServletFileUpload upload = new ServletFileUpload(factory);

// Parse the request
List /* FileItem */ items = upload.parseRequest(request);]]></source>
      <p>
        That's all that's needed. Really!
      </p>
      <p>
        The result of the parse is a <code>List</code> of file items, each of
        which implements the <code>FileItem</code> interface. Processing these
        items is discussed below.
      </p>
    </subsection>

    <subsection name="Exercising more control"> 
      <p>
        If your usage scenario is close to the simplest case, described above,
        but you need a little more control, you can easily customize the
        behavior of the upload handler or the file item factory or both. The
        following example shows several configuration options:
      </p>
<source><![CDATA[// Create a factory for disk-based file items
DiskFileItemFactory factory = new DiskFileItemFactory();

// Set factory constraints
factory.setSizeThreshold(yourMaxMemorySize);
factory.setRepository(yourTempDirectory);

// Create a new file upload handler
ServletFileUpload upload = new ServletFileUpload(factory);

// Set overall request size constraint
upload.setSizeMax(yourMaxRequestSize);

// Parse the request
List /* FileItem */ items = upload.parseRequest(request);]]></source>
      <p>
        Of course, each of the configuration methods is independent of the
        others, but if you want to configure the factory all at once, you can
        do that with an alternative constructor, like this:
      </p>
<source><![CDATA[// Create a factory for disk-based file items
DiskFileItemFactory factory = new DiskFileItemFactory(
        yourMaxMemorySize, yourTempDirectory);]]></source>
      <p>
        Should you need further control over the parsing of the request, such
        as storing the items elsewhere - for example, in a database - you will
        need to look into <a href="customizing.html">customizing</a> FileUpload.
      </p>
    </subsection>
  </section>

  <section name="Processing the uploaded items">
    <p>
      Once the parse has completed, you will have a <code>List</code> of file
      items that you need to process. In most cases, you will want to handle
      file uploads differently from regular form fields, so you might process
      the list like this:
    </p>
<source><![CDATA[// Process the uploaded items
Iterator iter = items.iterator();
while (iter.hasNext()) {
    FileItem item = (FileItem) iter.next();

    if (item.isFormField()) {
        processFormField(item);
    } else {
        processUploadedFile(item);
    }
}]]></source>
    <p>
      For a regular form field, you will most likely be interested only in the
      name of the item, and its <code>String</code> value. As you might expect,
      accessing these is very simple.
    </p>
<source><![CDATA[// Process a regular form field
if (item.isFormField()) {
    String name = item.getFieldName();
    String value = item.getString();
    ...
}]]></source>
    <p>
      For a file upload, there are several different things you might want to
      know before you process the content. Here is an example of some of the
      methods you might be interested in.
    </p>
<source><![CDATA[// Process a file upload
if (!item.isFormField()) {
    String fieldName = item.getFieldName();
    String fileName = item.getName();
    String contentType = item.getContentType();
    boolean isInMemory = item.isInMemory();
    long sizeInBytes = item.getSize();
    ...
}]]></source>
    <p>
      With uploaded files, you generally will not want to access them via
      memory, unless they are small, or unless you have no other alternative.
      Rather, you will want to process the content as a stream, or write the
      entire file to its ultimate location. FileUpload provides simple means of
      accomplishing both of these.
    </p>
<source><![CDATA[// Process a file upload
if (writeToFile) {
    File uploadedFile = new File(...);
    item.write(uploadedFile);
} else {
    InputStream uploadedStream = item.getInputStream();
    ...
    uploadedStream.close();
}]]></source>
    <p>
      Note that, in the default implementation of FileUpload, <code>write()</code>
      will attempt to rename the file to the specified destination, if the data
      is already in a temporary file. Actually copying the data is only done if
      the the rename fails, for some reason, or if the data was in memory.
    </p>
    <p>
      If you do need to access the uploaded data in memory, you need simply
      call the <code>get()</code> method to obtain the data as an array of
      bytes.
    </p>
<source><![CDATA[// Process a file upload in memory
byte[] data = item.get();
...]]></source>
  </section>

  <section name="Resource cleanup">
    <p>
      This section applies only, if you are using the
      <a href="apidocs/org/apache/commons/fileupload/disk/DiskFileItem.html">DiskFileItem</a>.
      In other words, it applies, if your uploaded files are written to
      temporary files before processing them.
    </p>
    <p>
      Such temporary files are deleted automatically, if they are no longer
      used (more precisely, if the corresponding instance of <code>java.io.File</code>
      is garbage collected. This is done silently by the <code>org.apache.commons.io.FileCleaner</code>
      class, which starts a reaper thread.
    </p>
    <p>
      This reaper thread should be stopped, if it is no longer needed. In
      a servlet environment, this is done by using a special servlet
      context listener, called
      <a href="apidocs/org/apache/commons/fileupload/servlet/FileCleanerCleanup.html">FileCleanerCleanup</a>.
      To do so, add a section like the following to your <code>web.xml</code>:
    </p>
<source><![CDATA[
<web-app>
  ...
  <listener>
    <listener-class>
      org.apache.commons.fileupload.servlet.FileCleanerCleanup
    </listener-class>
  </listener>
  ...
</web-app>
]]></source>

    <subsection name="Creating a DiskFileItemFactory">
      <p>
        The FileCleanerCleanup provides an instance of
        <code>org.apache.commons.io.FileCleaningTracker</code>. This
        instance must be used when creating a
        <code>org.apache.commons.fileupload.disk.DiskFileItemFactory</code>.
        This should be done by calling a method like the following:
      </p>
<source><![CDATA[
    public static DiskFileItemFactory newDiskFileItemFactory(ServletContext context,
                                                             File repository) {
        FileCleaningTracker fileCleaningTracker
            = FileCleanerCleanup.getFileCleaningTracker(context);
        return new DiskFileItemFactory(fileCleaningTracker,
                                       DiskFileItemFactory.DEFAULT_SIZE_THRESHOLD,
                                       repository);
    }
]]></source>
    </subsection>

    <subsection name="Disabling cleanup of temporary files">
      <p>
        To disable tracking of temporary files, you may set the
        <code>FileCleaningTracker</code> to null. Consequently,
        created files will no longer be tracked. In particular,
        they will no longer be deleted automatically.</p>
    </subsection>
  </section>

  <section name="Interaction with virus scanners">
    <p>
      Virus scanners running on the same system as the web container can cause
      some unexpected behaviours for applications using FileUpload. This section
      describes some of the behaviours that you might encounter, and provides
      some ideas for how to handle them.
    </p>
    <p>
      The default implementation of FileUpload will cause uploaded items above
      a certain size threshold to be written to disk. As soon as such a file is
      closed, any virus scanner on the system will wake up and inspect it, and
      potentially quarantine the file - that is, move it to a special location
      where it will not cause problems. This, of course, will be a surprise to
      the application developer, since the uploaded file item will no longer be
      available for processing. On the other hand, uploaded items below that
      same threshold will be held in memory, and therefore will not be seen by
      virus scanners. This allows for the possibility of a virus being retained
      in some form (although if it is ever written to disk, the virus scanner
      would locate and inspect it).
    </p>
    <p>
      One commonly used solution is to set aside one directory on the system
      into which all uploaded files will be placed, and to configure the virus
      scanner to ignore that directory. This ensures that files will not be
      ripped out from under the application, but then leaves responsibility for
      virus scanning up to the application developer. Scanning the uploaded
      files for viruses can then be performed by an external process, which
      might move clean or cleaned files to an "approved" location, or by
      integrating a virus scanner within the application itself. The details of
      configuring an external process or integrating virus scanning into an
      application are outside the scope of this document.
    </p>
  </section>

  <section name="Watching progress">
    <p>
      If you expect really large file uploads, then it would be nice to report
      to your users, how much is already received. Even HTML pages allow to
      implement a progress bar by returning a multipart/replace response,
      or something like that.
    </p>
    <p>
      Watching the upload progress may be done by supplying a progress listener:
    </p>
<source><![CDATA[//Create a progress listener
ProgressListener progressListener = new ProgressListener(){
   public void update(long pBytesRead, long pContentLength, int pItems) {
       System.out.println("We are currently reading item " + pItems);
       if (pContentLength == -1) {
           System.out.println("So far, " + pBytesRead + " bytes have been read.");
       } else {
           System.out.println("So far, " + pBytesRead + " of " + pContentLength
                              + " bytes have been read.");
       }
   }
};
upload.setProgressListener(progressListener);
]]></source>
    <p>
      Do yourself a favour and implement your first progress listener just
      like the above, because it shows you a pitfall: The progress listener
      is called quite frequently. Depending on the servlet engine and other
      environment factory, it may be called for any network packet! In
      other words, your progress listener may become a performance problem!
      A typical solution might be, to reduce the progress listeners activity.
      For example, you might emit a message only, if the number of megabytes
      has changed:
    </p>
<source><![CDATA[//Create a progress listener
ProgressListener progressListener = new ProgressListener(){
   private long megaBytes = -1;
   public void update(long pBytesRead, long pContentLength, int pItems) {
       long mBytes = pBytesRead / 1000000;
       if (megaBytes == mBytes) {
           return;
       }
       megaBytes = mBytes;
       System.out.println("We are currently reading item " + pItems);
       if (pContentLength == -1) {
           System.out.println("So far, " + pBytesRead + " bytes have been read.");
       } else {
           System.out.println("So far, " + pBytesRead + " of " + pContentLength
                              + " bytes have been read.");
       }
   }
};
]]></source>
  </section>

  <section name="What's next">
    <p>
      Hopefully this page has provided you with a good idea of how to use
      FileUpload in your own applications. For more detail on the methods
      introduced here, as well as other available methods, you should refer
      to the <a href="apidocs/index.html">JavaDocs</a>.
    </p>
    <p>
      The usage described here should satisfy a large majority of file upload
      needs. However, should you have more complex requirements, FileUpload
      should still be able to help you, with it's flexible
      <a href="customizing.html">customization</a> capabilities.
    </p>
  </section>

</body>
</document>