View Javadoc

1   /*
2    * Copyright 2004-2010 the Seasar Foundation and the Others.
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    *     http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
13   * either express or implied. See the License for the specific language
14   * governing permissions and limitations under the License.
15   */
16  
17  package org.seasar.cubby.fileupload;
18  
19  import java.io.ByteArrayInputStream;
20  import java.io.ByteArrayOutputStream;
21  import java.io.File;
22  import java.io.FileOutputStream;
23  import java.io.IOException;
24  import java.io.InputStream;
25  import java.io.OutputStream;
26  import java.io.UnsupportedEncodingException;
27  
28  import org.apache.commons.fileupload.FileItem;
29  import org.apache.commons.fileupload.FileItemFactory;
30  import org.apache.commons.fileupload.disk.DiskFileItemFactory;
31  
32  /**
33   * Streaming API によってマルチパート要求を処理するための {@link FileItemFactory} の実装です。
34   * <p>
35   * ローカルファイルへの書き込みに制限がある環境で {@link DiskFileItemFactory} の代わりに使用してください。
36   * </p>
37   * 
38   * @see <a
39   *      href="http://commons.apache.org/fileupload/streaming.html">Streaming&nbsp;API&nbsp;(commons-fileupload)</a>
40   * @author baba
41   */
42  public class StreamFileItemFactory implements FileItemFactory {
43  
44  	/** 初期バッファサイズのデフォルト。 */
45  	public static final int DEFAULT_INITIAL_BUFFER_SIZE = 8192;
46  
47  	/** 初期バッファサイズ。 */
48  	private int initialBufferSize = DEFAULT_INITIAL_BUFFER_SIZE;
49  
50  	/**
51  	 * 初期バッファサイズを設定します。
52  	 * 
53  	 * @param initialBufferSize
54  	 *            初期バッファサイズ
55  	 */
56  	public void setInitialBufferSize(final int initialBufferSize) {
57  		this.initialBufferSize = initialBufferSize;
58  	}
59  
60  	/**
61  	 * {@inheritDoc}
62  	 */
63  	public FileItem createItem(final String fieldName,
64  			final String contentType, final boolean isFormField,
65  			final String fileName) {
66  		return new ByteArrayFileItem(fieldName, contentType, isFormField,
67  				fileName, initialBufferSize);
68  	}
69  
70  	/**
71  	 * バイト配列にデータを保持する {@link FileItem} の実装です。
72  	 * 
73  	 * @author baba
74  	 */
75  	private static class ByteArrayFileItem implements FileItem {
76  
77  		private static final long serialVersionUID = 1L;
78  
79  		/** フィールド名。 */
80  		private String fieldName;
81  
82  		/** コンテントタイプ。 */
83  		private final String contentType;
84  
85  		/** フォームフィールドか。 */
86  		private boolean isFormField;
87  
88  		/** ファイル名。 */
89  		private final String fileName;
90  
91  		/** 初期バッファサイズ。 */
92  		private final int initialBufferSize;
93  
94  		/** 出力ストリーム。 */
95  		private transient ByteArrayOutputStream outputStream;
96  
97  		/** データ。 */
98  		private byte[] data;
99  
100 		/**
101 		 * インスタンス化します。
102 		 * 
103 		 * @param fieldName
104 		 *            フィールド名
105 		 * @param contentType
106 		 *            コンテントタイプ
107 		 * @param isFormField
108 		 *            フォームフィールドか
109 		 * @param fileName
110 		 *            ファイル名
111 		 * @param initialBufferSize
112 		 *            初期バッファサイズ
113 		 */
114 		public ByteArrayFileItem(final String fieldName,
115 				final String contentType, final boolean isFormField,
116 				final String fileName, final int initialBufferSize) {
117 			this.fieldName = fieldName;
118 			this.contentType = contentType;
119 			this.isFormField = isFormField;
120 			this.fileName = fileName;
121 			this.initialBufferSize = initialBufferSize;
122 		}
123 
124 		/**
125 		 * {@inheritDoc}
126 		 */
127 		public InputStream getInputStream() throws IOException {
128 			return new ByteArrayInputStream(get());
129 		}
130 
131 		/**
132 		 * {@inheritDoc}
133 		 */
134 		public String getContentType() {
135 			return contentType;
136 		}
137 
138 		/**
139 		 * {@inheritDoc}
140 		 */
141 		public String getName() {
142 			return fileName;
143 		}
144 
145 		/**
146 		 * {@inheritDoc}
147 		 */
148 		public boolean isInMemory() {
149 			return true;
150 		}
151 
152 		/**
153 		 * {@inheritDoc}
154 		 */
155 		public long getSize() {
156 			return get().length;
157 		}
158 
159 		/**
160 		 * {@inheritDoc}
161 		 */
162 		public byte[] get() {
163 			if (data == null) {
164 				data = outputStream.toByteArray();
165 			}
166 			return data;
167 		}
168 
169 		/**
170 		 * {@inheritDoc}
171 		 */
172 		public String getString(final String encoding)
173 				throws UnsupportedEncodingException {
174 			return new String(get(), encoding);
175 		}
176 
177 		/**
178 		 * {@inheritDoc}
179 		 */
180 		public String getString() {
181 			return new String(get());
182 		}
183 
184 		/**
185 		 * {@inheritDoc}
186 		 */
187 		public void write(final File file) throws Exception {
188 			final FileOutputStream out = new FileOutputStream(file);
189 			try {
190 				out.write(get());
191 			} finally {
192 				if (out != null) {
193 					out.close();
194 				}
195 			}
196 		}
197 
198 		/**
199 		 * {@inheritDoc}
200 		 */
201 		public void delete() {
202 			this.data = null;
203 		}
204 
205 		/**
206 		 * {@inheritDoc}
207 		 */
208 		public String getFieldName() {
209 			return fieldName;
210 		}
211 
212 		/**
213 		 * {@inheritDoc}
214 		 */
215 		public void setFieldName(final String name) {
216 			this.fieldName = name;
217 		}
218 
219 		/**
220 		 * {@inheritDoc}
221 		 */
222 		public boolean isFormField() {
223 			return isFormField;
224 		}
225 
226 		/**
227 		 * {@inheritDoc}
228 		 */
229 		public void setFormField(final boolean state) {
230 			this.isFormField = state;
231 		}
232 
233 		/**
234 		 * {@inheritDoc}
235 		 */
236 		public OutputStream getOutputStream() {
237 			if (outputStream == null) {
238 				outputStream = new ByteArrayOutputStream(initialBufferSize);
239 			}
240 			return outputStream;
241 		}
242 
243 	}
244 }