View Javadoc
1   /*
2    * Copyright 2012 The Netty Project
3    *
4    * The Netty Project licenses this file to you under the Apache License,
5    * version 2.0 (the "License"); you may not use this file except in compliance
6    * with the License. You may obtain a copy of the License at:
7    *
8    *   https://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, WITHOUT
12   * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13   * License for the specific language governing permissions and limitations
14   * under the License.
15   */
16  package io.netty.handler.codec.http.multipart;
17  
18  import io.netty.buffer.ByteBuf;
19  
20  import java.io.File;
21  import java.io.IOException;
22  import java.io.InputStream;
23  import java.nio.charset.Charset;
24  
25  /**
26   * Mixed implementation using both in Memory and in File with a limit of size
27   */
28  public class MixedFileUpload implements FileUpload {
29  
30      private final String baseDir;
31  
32      private final boolean deleteOnExit;
33  
34      private FileUpload fileUpload;
35  
36      private final long limitSize;
37  
38      private final long definedSize;
39      private long maxSize = DefaultHttpDataFactory.MAXSIZE;
40  
41      public MixedFileUpload(String name, String filename, String contentType,
42              String contentTransferEncoding, Charset charset, long size,
43              long limitSize) {
44          this(name, filename, contentType, contentTransferEncoding,
45                  charset, size, limitSize, DiskFileUpload.baseDirectory, DiskFileUpload.deleteOnExitTemporaryFile);
46      }
47  
48      public MixedFileUpload(String name, String filename, String contentType,
49              String contentTransferEncoding, Charset charset, long size,
50              long limitSize, String baseDir, boolean deleteOnExit) {
51          this.limitSize = limitSize;
52          if (size > this.limitSize) {
53              fileUpload = new DiskFileUpload(name, filename, contentType,
54                      contentTransferEncoding, charset, size);
55          } else {
56              fileUpload = new MemoryFileUpload(name, filename, contentType,
57                      contentTransferEncoding, charset, size);
58          }
59          definedSize = size;
60          this.baseDir = baseDir;
61          this.deleteOnExit = deleteOnExit;
62      }
63  
64      @Override
65      public long getMaxSize() {
66          return maxSize;
67      }
68  
69      @Override
70      public void setMaxSize(long maxSize) {
71          this.maxSize = maxSize;
72          fileUpload.setMaxSize(maxSize);
73      }
74  
75      @Override
76      public void checkSize(long newSize) throws IOException {
77          if (maxSize >= 0 && newSize > maxSize) {
78              throw new IOException("Size exceed allowed maximum capacity");
79          }
80      }
81  
82      @Override
83      public void addContent(ByteBuf buffer, boolean last)
84              throws IOException {
85          if (fileUpload instanceof MemoryFileUpload) {
86              try {
87                  checkSize(fileUpload.length() + buffer.readableBytes());
88                  if (fileUpload.length() + buffer.readableBytes() > limitSize) {
89                      DiskFileUpload diskFileUpload = new DiskFileUpload(fileUpload
90                              .getName(), fileUpload.getFilename(), fileUpload
91                              .getContentType(), fileUpload
92                              .getContentTransferEncoding(), fileUpload.getCharset(),
93                              definedSize, baseDir, deleteOnExit);
94                      diskFileUpload.setMaxSize(maxSize);
95                      ByteBuf data = fileUpload.getByteBuf();
96                      if (data != null && data.isReadable()) {
97                          diskFileUpload.addContent(data.retain(), false);
98                      }
99                      // release old upload
100                     fileUpload.release();
101 
102                     fileUpload = diskFileUpload;
103                 }
104             } catch (IOException e) {
105                 buffer.release();
106                 throw e;
107             }
108         }
109         fileUpload.addContent(buffer, last);
110     }
111 
112     @Override
113     public void delete() {
114         fileUpload.delete();
115     }
116 
117     @Override
118     public byte[] get() throws IOException {
119         return fileUpload.get();
120     }
121 
122     @Override
123     public ByteBuf getByteBuf() throws IOException {
124         return fileUpload.getByteBuf();
125     }
126 
127     @Override
128     public Charset getCharset() {
129         return fileUpload.getCharset();
130     }
131 
132     @Override
133     public String getContentType() {
134         return fileUpload.getContentType();
135     }
136 
137     @Override
138     public String getContentTransferEncoding() {
139         return fileUpload.getContentTransferEncoding();
140     }
141 
142     @Override
143     public String getFilename() {
144         return fileUpload.getFilename();
145     }
146 
147     @Override
148     public String getString() throws IOException {
149         return fileUpload.getString();
150     }
151 
152     @Override
153     public String getString(Charset encoding) throws IOException {
154         return fileUpload.getString(encoding);
155     }
156 
157     @Override
158     public boolean isCompleted() {
159         return fileUpload.isCompleted();
160     }
161 
162     @Override
163     public boolean isInMemory() {
164         return fileUpload.isInMemory();
165     }
166 
167     @Override
168     public long length() {
169         return fileUpload.length();
170     }
171 
172     @Override
173     public long definedLength() {
174         return fileUpload.definedLength();
175     }
176 
177     @Override
178     public boolean renameTo(File dest) throws IOException {
179         return fileUpload.renameTo(dest);
180     }
181 
182     @Override
183     public void setCharset(Charset charset) {
184         fileUpload.setCharset(charset);
185     }
186 
187     @Override
188     public void setContent(ByteBuf buffer) throws IOException {
189         try {
190             checkSize(buffer.readableBytes());
191         } catch (IOException e) {
192             buffer.release();
193             throw e;
194         }
195         if (buffer.readableBytes() > limitSize) {
196             if (fileUpload instanceof MemoryFileUpload) {
197                 FileUpload memoryUpload = fileUpload;
198                 // change to Disk
199                 fileUpload = new DiskFileUpload(memoryUpload
200                         .getName(), memoryUpload.getFilename(), memoryUpload
201                         .getContentType(), memoryUpload
202                         .getContentTransferEncoding(), memoryUpload.getCharset(),
203                         definedSize, baseDir, deleteOnExit);
204                 fileUpload.setMaxSize(maxSize);
205 
206                 // release old upload
207                 memoryUpload.release();
208             }
209         }
210         fileUpload.setContent(buffer);
211     }
212 
213     @Override
214     public void setContent(File file) throws IOException {
215         checkSize(file.length());
216         if (file.length() > limitSize) {
217             if (fileUpload instanceof MemoryFileUpload) {
218                 FileUpload memoryUpload = fileUpload;
219 
220                 // change to Disk
221                 fileUpload = new DiskFileUpload(memoryUpload
222                         .getName(), memoryUpload.getFilename(), memoryUpload
223                         .getContentType(), memoryUpload
224                         .getContentTransferEncoding(), memoryUpload.getCharset(),
225                         definedSize, baseDir, deleteOnExit);
226                 fileUpload.setMaxSize(maxSize);
227 
228                 // release old upload
229                 memoryUpload.release();
230             }
231         }
232         fileUpload.setContent(file);
233     }
234 
235     @Override
236     public void setContent(InputStream inputStream) throws IOException {
237         if (fileUpload instanceof MemoryFileUpload) {
238             FileUpload memoryUpload = fileUpload;
239 
240             // change to Disk
241             fileUpload = new DiskFileUpload(fileUpload
242                     .getName(), fileUpload.getFilename(), fileUpload
243                     .getContentType(), fileUpload
244                     .getContentTransferEncoding(), fileUpload.getCharset(),
245                     definedSize, baseDir, deleteOnExit);
246             fileUpload.setMaxSize(maxSize);
247 
248             // release old upload
249             memoryUpload.release();
250         }
251         fileUpload.setContent(inputStream);
252     }
253 
254     @Override
255     public void setContentType(String contentType) {
256         fileUpload.setContentType(contentType);
257     }
258 
259     @Override
260     public void setContentTransferEncoding(String contentTransferEncoding) {
261         fileUpload.setContentTransferEncoding(contentTransferEncoding);
262     }
263 
264     @Override
265     public void setFilename(String filename) {
266         fileUpload.setFilename(filename);
267     }
268 
269     @Override
270     public HttpDataType getHttpDataType() {
271         return fileUpload.getHttpDataType();
272     }
273 
274     @Override
275     public String getName() {
276         return fileUpload.getName();
277     }
278 
279     @Override
280     public int hashCode() {
281         return fileUpload.hashCode();
282     }
283 
284     @Override
285     public boolean equals(Object obj) {
286         return fileUpload.equals(obj);
287     }
288 
289     @Override
290     public int compareTo(InterfaceHttpData o) {
291         return fileUpload.compareTo(o);
292     }
293 
294     @Override
295     public String toString() {
296         return "Mixed: " + fileUpload;
297     }
298 
299     @Override
300     public ByteBuf getChunk(int length) throws IOException {
301         return fileUpload.getChunk(length);
302     }
303 
304     @Override
305     public File getFile() throws IOException {
306         return fileUpload.getFile();
307     }
308 
309     @Override
310     public FileUpload copy() {
311         return fileUpload.copy();
312     }
313 
314     @Override
315     public FileUpload duplicate() {
316         return fileUpload.duplicate();
317     }
318 
319     @Override
320     public FileUpload retainedDuplicate() {
321         return fileUpload.retainedDuplicate();
322     }
323 
324     @Override
325     public FileUpload replace(ByteBuf content) {
326         return fileUpload.replace(content);
327     }
328 
329     @Override
330     public ByteBuf content() {
331         return fileUpload.content();
332     }
333 
334     @Override
335     public int refCnt() {
336         return fileUpload.refCnt();
337     }
338 
339     @Override
340     public FileUpload retain() {
341         fileUpload.retain();
342         return this;
343     }
344 
345     @Override
346     public FileUpload retain(int increment) {
347         fileUpload.retain(increment);
348         return this;
349     }
350 
351     @Override
352     public FileUpload touch() {
353         fileUpload.touch();
354         return this;
355     }
356 
357     @Override
358     public FileUpload touch(Object hint) {
359         fileUpload.touch(hint);
360         return this;
361     }
362 
363     @Override
364     public boolean release() {
365         return fileUpload.release();
366     }
367 
368     @Override
369     public boolean release(int decrement) {
370         return fileUpload.release(decrement);
371     }
372 }