View Javadoc

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