1 24 package org.riotfamily.forms.element.upload; 25 26 import java.io.File ; 27 import java.io.FileInputStream ; 28 import java.io.IOException ; 29 import java.io.PrintWriter ; 30 31 import javax.activation.MimetypesFileTypeMap ; 32 import javax.servlet.http.HttpServletRequest ; 33 import javax.servlet.http.HttpServletResponse ; 34 35 import org.riotfamily.common.util.FormatUtils; 36 import org.riotfamily.common.web.file.FileStore; 37 import org.riotfamily.forms.CompositeElement; 38 import org.riotfamily.forms.ContentElement; 39 import org.riotfamily.forms.Editor; 40 import org.riotfamily.forms.EditorBinder; 41 import org.riotfamily.forms.Element; 42 import org.riotfamily.forms.ErrorUtils; 43 import org.riotfamily.forms.element.TemplateElement; 44 import org.riotfamily.forms.event.Button; 45 import org.riotfamily.forms.event.JavaScriptEvent; 46 import org.riotfamily.forms.event.JavaScriptEventAdapter; 47 import org.riotfamily.forms.fileupload.UploadStatus; 48 import org.riotfamily.forms.request.FormRequest; 49 import org.riotfamily.forms.resource.FormResource; 50 import org.riotfamily.forms.resource.ResourceElement; 51 import org.riotfamily.forms.resource.ScriptResource; 52 import org.riotfamily.forms.resource.StylesheetResource; 53 import org.springframework.util.Assert; 54 import org.springframework.util.FileCopyUtils; 55 import org.springframework.util.ObjectUtils; 56 import org.springframework.util.StringUtils; 57 import org.springframework.web.multipart.MultipartFile; 58 59 60 63 public class FileUpload extends CompositeElement implements Editor, 64 ResourceElement { 65 66 private static MimetypesFileTypeMap defaultMimetypesMap = 67 new MimetypesFileTypeMap (); 68 69 protected static FormResource RESOURCE = new ScriptResource( 70 "form/fileupload/upload.js", null, 71 new StylesheetResource("form/fileupload/progress.css")); 72 73 private String filenameProperty; 74 75 private String contentTypeProperty; 76 77 private String sizeProperty; 78 79 private MimetypesFileTypeMap mimetypesMap; 80 81 private FileStore fileStore; 82 83 private String uri; 84 85 private File file; 86 87 private File tempFile; 88 89 private File returnedFile; 90 91 private String fileName; 92 93 private String contentType; 94 95 private Long size; 96 97 98 public FileUpload() { 99 addComponent(new UploadElement()); 100 addComponent(new RemoveButton()); 101 addComponent(createPreviewElement()); 102 setSurroundBySpan(true); 103 } 104 105 protected Element createPreviewElement() { 106 return new PreviewElement(); 107 } 108 109 public FileStore getFileStore() { 110 return this.fileStore; 111 } 112 113 public void setFileStore(FileStore fileStore) { 114 this.fileStore = fileStore; 115 } 116 117 public FormResource getResource() { 118 return RESOURCE; 119 } 120 121 public void setFilenameProperty(String property) { 122 this.filenameProperty = property; 123 } 124 125 public void setContentTypeProperty(String property) { 126 this.contentTypeProperty = property; 127 } 128 129 public void setSizeProperty(String property) { 130 this.sizeProperty = property; 131 } 132 133 public String getSizeProperty() { 134 return this.sizeProperty; 135 } 136 137 public String getContentType() { 138 return contentType; 139 } 140 141 public String getFileName() { 142 return fileName; 143 } 144 145 public Long getSize() { 146 return size; 147 } 148 149 public String getFormatedSize() { 150 if (size != null) { 151 return FormatUtils.formatByteSize(size.longValue()); 152 } 153 return null; 154 } 155 156 public boolean isPresent() { 157 return file != null; 158 } 159 160 protected File getFile() { 161 return this.file; 162 } 163 164 protected void setFile(File file) { 165 this.file = file; 166 this.size = new Long (file.length()); 167 revalidate(); 168 } 169 170 protected void afterFileUploaded() { 171 } 172 173 protected File getTempFile() { 174 return tempFile; 175 } 176 177 protected File getReturnedFile() { 178 return returnedFile; 179 } 180 181 protected void setContentType(String contentType) { 182 this.contentType = contentType; 183 } 184 185 public void setMimetypesMap(MimetypesFileTypeMap mimetypesMap) { 186 this.mimetypesMap = mimetypesMap; 187 } 188 189 protected String contentType(File file) { 190 if (mimetypesMap == null) { 191 mimetypesMap = defaultMimetypesMap; 192 } 193 return mimetypesMap.getContentType(file); 194 } 195 196 public void setValue(Object value) { 197 log.debug("Value set to: " + value); 198 if (value == null) { 199 return; 200 } 201 if (fileStore != null) { 202 if (!(value instanceof String )) { 203 throw new IllegalArgumentException ("Value is not a String: " + value); 204 } 205 uri = (String ) value; 206 file = fileStore.retrieve(uri); 207 Assert.notNull(file, "File not found in FileStore: " + uri); 208 } 209 else { 210 if (!(value instanceof File )) { 211 throw new IllegalArgumentException ("Value is not a File: " + value); 212 } 213 uri = null; 214 file = (File ) value; 215 } 216 217 EditorBinder editorBinder = getEditorBinding().getEditorBinder(); 218 if (filenameProperty != null) { 219 fileName = (String ) editorBinder.getPropertyValue(filenameProperty); 220 } 221 else { 222 fileName = file.getName(); 223 } 224 225 if (contentTypeProperty != null) { 226 contentType = (String ) editorBinder.getPropertyValue(contentTypeProperty); 227 } 228 else { 229 contentType = contentType(file); 230 } 231 size = new Long (file.length()); 232 } 233 234 public Object getValue() { 235 EditorBinder editorBinder = getEditorBinding().getEditorBinder(); 236 if (filenameProperty != null) { 237 editorBinder.setPropertyValue(filenameProperty, fileName); 238 } 239 if (contentTypeProperty != null) { 240 editorBinder.setPropertyValue(contentTypeProperty, contentType); 241 } 242 if (sizeProperty != null) { 243 editorBinder.setPropertyValue(sizeProperty, size); 244 } 245 246 if (fileStore != null) { 247 File originalFile = uri != null ? fileStore.retrieve(uri) : null; 248 if (!ObjectUtils.nullSafeEquals(originalFile, file)) { 249 try { 250 if (uri != null) { 251 fileStore.delete(uri); 252 } 253 if (file != null) { 254 uri = fileStore.store(file, FormatUtils.toFilename(fileName)); 255 file = fileStore.retrieve(uri); 256 returnedFile = file; 257 } 258 else { 259 uri = null; 260 } 261 } 262 catch (IOException e) { 263 throw new RuntimeException ("Failed to store file: " 264 + e.getMessage(), e); 265 } 266 } 267 return uri; 268 } 269 else { 270 returnedFile = file; 271 return file; 272 } 273 } 274 275 protected void destroy() { 276 if (tempFile != null && !tempFile.equals(returnedFile)) { 277 tempFile.delete(); 278 } 279 } 280 281 protected final void finalize() throws Throwable { 282 super.finalize(); 283 destroy(); 284 } 285 286 protected final void validate() { 287 if (isRequired() && file == null) { 288 ErrorUtils.rejectRequired(this); 289 } 290 if (file != null) { 291 validateFile(file); 292 } 293 } 294 295 protected void validateFile(File file) { 296 } 297 298 302 public boolean isCompositeElement() { 303 return false; 304 } 305 306 public class UploadElement extends TemplateElement 307 implements JavaScriptEventAdapter { 308 309 private String uploadId; 310 311 private UploadStatus status; 312 313 public UploadElement() { 314 this.uploadId = UploadStatus.createUploadId(); 315 } 316 317 public String getUploadId() { 318 return uploadId; 319 } 320 321 public String getUploadUrl() { 322 return getFormContext().getUploadUrl(uploadId); 323 } 324 325 public UploadStatus getStatus() { 326 return status; 327 } 328 329 public void processRequestInternal(FormRequest request) { 330 log.debug("Processing " + getParamName()); 331 MultipartFile multipartFile = request.getFile(getParamName()); 332 if ((multipartFile != null) && (!multipartFile.isEmpty())) { 333 try { 334 fileName = multipartFile.getOriginalFilename(); 335 contentType = multipartFile.getContentType(); 336 if (tempFile != null) { 337 tempFile.delete(); 338 } 339 String ext = FormatUtils.getExtension(fileName); 340 if (StringUtils.hasLength(ext)) { 341 ext = '.' + ext; 342 } 343 tempFile = File.createTempFile("000", ext); 344 345 multipartFile.transferTo(tempFile); 346 log.debug("stored at: " + tempFile.getAbsolutePath()); 347 348 setFile(tempFile); 349 afterFileUploaded(); 350 351 log.debug("File uploaded: " + fileName + " (" 352 + contentType + ")"); 353 354 } 355 catch (IOException e) { 356 log.error("error saving uploaded file"); 357 } 358 } 359 } 360 361 364 public int getEventTypes() { 365 return 0; 366 } 367 368 371 public void handleJavaScriptEvent(JavaScriptEvent event) { 372 status = UploadStatus.getStatus(uploadId); 373 if (getFormListener() != null) { 374 getFormListener().elementChanged(this); 375 if (status != null) { 376 log.debug("Progress: " + status.getProgress()); 377 getFormListener().refresh(this); 378 } 379 else { 380 log.debug("No status."); 381 getFormListener().elementChanged(FileUpload.this); 382 } 383 } 384 } 385 386 } 387 388 private class RemoveButton extends Button { 389 390 private RemoveButton() { 391 setCssClass("remove-file"); 392 } 393 394 public String getLabel() { 395 return "Remove"; 396 } 397 398 protected void onClick() { 399 file = null; 400 ErrorUtils.removeErrors(FileUpload.this); 401 if (getFormListener() != null) { 402 getFormListener().elementChanged(FileUpload.this); 403 } 404 } 405 406 public void render(PrintWriter writer) { 407 if (!FileUpload.this.isRequired() && isPresent()) { 408 super.render(writer); 409 } 410 } 411 412 public int getEventTypes() { 413 return JavaScriptEvent.ON_CLICK; 414 } 415 } 416 417 public class PreviewElement extends TemplateElement 418 implements ContentElement { 419 420 public PreviewElement() { 421 setAttribute("file", FileUpload.this); 422 } 423 424 public void handleContentRequest(HttpServletRequest request, 425 HttpServletResponse response) throws IOException { 426 427 if (file != null && file.exists()) { 428 response.setDateHeader("Expires", 0); 429 response.setHeader("Content-Type", "application/x-download"); 430 response.setHeader("Content-Disposition", 431 "attachment;filename=" + fileName); 432 433 response.setContentLength(size.intValue()); 434 FileCopyUtils.copy(new FileInputStream (file), 435 response.getOutputStream()); 436 } 437 else { 438 response.sendError(HttpServletResponse.SC_NO_CONTENT); 439 } 440 } 441 442 public String getDownloadUrl() { 443 return getFormContext().getContentUrl(this); 444 } 445 446 } 447 448 449 } 450 | Popular Tags |