|
15 | 15 | from ckan.common import config |
16 | 16 |
|
17 | 17 | ALLOWED_UPLOAD_TYPES = (cgi.FieldStorage, FlaskFileStorage) |
| 18 | +MB = 1 << 20 |
| 19 | + |
18 | 20 | log = logging.getLogger(__name__) |
19 | 21 |
|
20 | 22 | _storage_path = None |
21 | 23 | _max_resource_size = None |
22 | 24 | _max_image_size = None |
23 | 25 |
|
24 | 26 |
|
| 27 | +def _copy_file(input_file, output_file, max_size): |
| 28 | + input_file.seek(0) |
| 29 | + current_size = 0 |
| 30 | + while True: |
| 31 | + current_size = current_size + 1 |
| 32 | + # MB chunks |
| 33 | + data = input_file.read(MB) |
| 34 | + |
| 35 | + if not data: |
| 36 | + break |
| 37 | + output_file.write(data) |
| 38 | + if current_size > max_size: |
| 39 | + raise logic.ValidationError({'upload': ['File upload too large']}) |
| 40 | + |
| 41 | + |
25 | 42 | def _get_underlying_file(wrapper): |
26 | 43 | if isinstance(wrapper, FlaskFileStorage): |
27 | 44 | return wrapper.stream |
@@ -162,22 +179,14 @@ def upload(self, max_size=2): |
162 | 179 | max_size is size in MB maximum of the file''' |
163 | 180 |
|
164 | 181 | if self.filename: |
165 | | - output_file = open(self.tmp_filepath, 'wb') |
166 | | - self.upload_file.seek(0) |
167 | | - current_size = 0 |
168 | | - while True: |
169 | | - current_size = current_size + 1 |
170 | | - # MB chunks |
171 | | - data = self.upload_file.read(2 ** 20) |
172 | | - if not data: |
173 | | - break |
174 | | - output_file.write(data) |
175 | | - if current_size > max_size: |
| 182 | + with open(self.tmp_filepath, 'wb+') as output_file: |
| 183 | + try: |
| 184 | + _copy_file(self.upload_file, output_file, max_size) |
| 185 | + except logic.ValidationError: |
176 | 186 | os.remove(self.tmp_filepath) |
177 | | - raise logic.ValidationError( |
178 | | - {self.file_field: ['File upload too large']} |
179 | | - ) |
180 | | - output_file.close() |
| 187 | + raise |
| 188 | + finally: |
| 189 | + self.upload_file.close() |
181 | 190 | os.rename(self.tmp_filepath, self.filepath) |
182 | 191 | self.clear = True |
183 | 192 |
|
@@ -285,24 +294,14 @@ def upload(self, id, max_size=10): |
285 | 294 | if e.errno != 17: |
286 | 295 | raise |
287 | 296 | tmp_filepath = filepath + '~' |
288 | | - output_file = open(tmp_filepath, 'wb+') |
289 | | - self.upload_file.seek(0) |
290 | | - current_size = 0 |
291 | | - while True: |
292 | | - current_size = current_size + 1 |
293 | | - # MB chunks |
294 | | - data = self.upload_file.read(2 ** 20) |
295 | | - |
296 | | - if not data: |
297 | | - break |
298 | | - output_file.write(data) |
299 | | - if current_size > max_size: |
| 297 | + with open(tmp_filepath, 'wb+') as output_file: |
| 298 | + try: |
| 299 | + _copy_file(self.upload_file, output_file, max_size) |
| 300 | + except logic.ValidationError: |
300 | 301 | os.remove(tmp_filepath) |
301 | | - raise logic.ValidationError( |
302 | | - {'upload': ['File upload too large']} |
303 | | - ) |
304 | | - |
305 | | - output_file.close() |
| 302 | + raise |
| 303 | + finally: |
| 304 | + self.upload_file.close() |
306 | 305 | os.rename(tmp_filepath, filepath) |
307 | 306 | return |
308 | 307 |
|
|
0 commit comments