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 import java.net.SocketException ; 31 32 import javax.servlet.http.HttpServletRequest ; 33 import javax.servlet.http.HttpServletResponse ; 34 35 import org.devlib.schmidt.imageinfo.ImageInfo; 36 import org.riotfamily.common.image.ImageCropper; 37 import org.riotfamily.common.markup.Html; 38 import org.riotfamily.common.markup.TagWriter; 39 import org.riotfamily.common.web.util.ServletUtils; 40 import org.riotfamily.forms.AbstractElement; 41 import org.riotfamily.forms.ContentElement; 42 import org.riotfamily.forms.DHTMLElement; 43 import org.riotfamily.forms.EditorBinder; 44 import org.riotfamily.forms.Element; 45 import org.riotfamily.forms.ErrorUtils; 46 import org.riotfamily.forms.TemplateUtils; 47 import org.riotfamily.forms.resource.FormResource; 48 import org.riotfamily.forms.resource.ResourceElement; 49 import org.riotfamily.forms.resource.Resources; 50 import org.riotfamily.forms.resource.ScriptResource; 51 import org.springframework.util.FileCopyUtils; 52 import org.springframework.web.bind.ServletRequestUtils; 53 54 57 public class ImageUpload extends FileUpload { 58 59 private static final FormResource PREVIEW_RESOURCE = new ScriptResource( 60 "riot-js/image-cropper.js", "Cropper", 61 Resources.SCRIPTACULOUS_SLIDER); 62 63 private int[] widths; 64 65 private int[] heights; 66 67 private int minWidth; 68 69 private int maxWidth; 70 71 private int minHeight; 72 73 private int maxHeight; 74 75 private String validFormats = "GIF,JPEG,PNG"; 76 77 private String widthProperty; 78 79 private String heightProperty; 80 81 private ImageInfo info; 82 83 private ImageCropper cropper; 84 85 private boolean crop = true; 86 87 private File originalFile; 88 89 private File croppedFile; 90 91 public ImageUpload() { 92 } 93 94 protected Element createPreviewElement() { 95 return new PreviewElement(); 96 } 97 98 public void setCropper(ImageCropper cropper) { 99 this.cropper = cropper; 100 } 101 102 public void setCrop(boolean crop) { 103 this.crop = crop; 104 } 105 106 public void setWidths(int[] widths) { 107 this.widths = widths; 108 if (widths != null) { 109 int min = Integer.MAX_VALUE; 110 int max = 0; 111 for (int i = 0; i < widths.length; i++) { 112 min = Math.min(min, widths[i]); 113 max = Math.max(max, widths[i]); 114 } 115 setMinWidth(min); 116 setMaxWidth(max); 117 } 118 } 119 120 public void setWidth(int width) { 121 setWidths(new int[] { width }); 122 } 123 124 public void setHeights(int[] heights) { 125 this.heights = heights; 126 if (heights != null) { 127 int min = Integer.MAX_VALUE; 128 int max = 0; 129 for (int i = 0; i < heights.length; i++) { 130 min = Math.min(min, heights[i]); 131 max = Math.max(max, heights[i]); 132 } 133 setMinHeight(min); 134 setMaxHeight(max); 135 } 136 } 137 138 public void setHeight(int height) { 139 setHeights(new int[] {height}); 140 } 141 142 public void setMinWidth(int minWidth) { 143 this.minWidth = minWidth; 144 } 145 146 public void setMaxWidth(int maxWidth) { 147 this.maxWidth = maxWidth; 148 } 149 150 public void setMinHeight(int minHeight) { 151 this.minHeight = minHeight; 152 } 153 154 public void setMaxHeight(int maxHeight) { 155 this.maxHeight = maxHeight; 156 } 157 158 public void setValidFormats(String validFormats) { 159 this.validFormats = validFormats; 160 } 161 162 public String getHeightProperty() { 163 return this.heightProperty; 164 } 165 166 public void setHeightProperty(String heightProperty) { 167 this.heightProperty = heightProperty; 168 } 169 170 public String getWidthProperty() { 171 return this.widthProperty; 172 } 173 174 public void setWidthProperty(String widthProperty) { 175 this.widthProperty = widthProperty; 176 } 177 178 public boolean isPreviewAvailable() { 179 return true; 180 } 181 182 protected void cropImage(int width, int height, int x, int y, 183 int scaledWidth) throws IOException { 184 185 if (croppedFile == null) { 186 croppedFile = File.createTempFile("000", ".tmp"); 187 } 188 if (originalFile == null) { 189 originalFile = getFile(); 190 } 191 cropper.cropImage(originalFile, croppedFile, width, height, x, y, 192 scaledWidth); 193 194 setFile(croppedFile); 195 } 196 197 protected void afterFileUploaded() { 198 originalFile = getFile(); 199 } 200 201 protected void undoCrop() { 202 setFile(originalFile); 203 } 204 205 protected void destroy() { 206 super.destroy(); 207 if (croppedFile != null && !croppedFile.equals(getReturnedFile())) { 208 croppedFile.delete(); 209 } 210 } 211 212 protected void validateFile(File file) { 213 try { 214 info = new ImageInfo(); 215 info.setInput(new FileInputStream (file)); 216 info.check(); 217 log.debug(info.getFormatName() + " Size: " 218 + info.getWidth() + "x" + info.getHeight()); 219 220 if (validFormats != null) { 221 if (validFormats.indexOf(info.getFormatName()) == -1) { 222 ErrorUtils.reject(this, "image.invalidFormat", 223 new Object [] { validFormats, info.getFormatName() }); 224 } 225 } 226 int imageHeight = info.getHeight(); 227 int imageWidth = info.getWidth(); 228 229 if (widths != null) { 230 boolean match = false; 231 for (int i = 0; i < widths.length; i++) { 232 if (imageWidth == widths[i]) { 233 match = true; 234 break; 235 } 236 } 237 if (!match) { 238 ErrorUtils.reject(this, "image.size.mismatch"); 239 return; 240 } 241 } 242 else if (imageWidth < minWidth || (maxWidth > 0 && imageWidth > maxWidth)) { 243 ErrorUtils.reject(this, "image.size.mismatch"); 244 return; 245 } 246 247 if (heights != null) { 248 boolean match = false; 249 for (int i = 0; i < heights.length; i++) { 250 if (imageHeight == heights[i]) { 251 match = true; 252 break; 253 } 254 } 255 if (!match) { 256 ErrorUtils.reject(this, "image.size.mismatch"); 257 } 258 } 259 else if (imageHeight < minHeight || (maxHeight > 0 && imageHeight > maxHeight)) { 260 ErrorUtils.reject(this, "image.size.mismatch"); 261 } 262 } 263 catch (IOException e) { 264 } 265 } 266 267 public Object getValue() { 268 if (info != null) { 269 EditorBinder editorBinder = getEditorBinding().getEditorBinder(); 270 if (widthProperty != null) { 271 editorBinder.setPropertyValue(widthProperty, 272 new Integer (info.getWidth())); 273 } 274 if (heightProperty != null) { 275 editorBinder.setPropertyValue(heightProperty, 276 new Integer (info.getHeight())); 277 } 278 } 279 return super.getValue(); 280 } 281 282 public class PreviewElement extends AbstractElement 283 implements ContentElement, DHTMLElement, ResourceElement { 284 285 public FormResource getResource() { 286 return PREVIEW_RESOURCE; 287 } 288 289 protected void renderInternal(PrintWriter writer) { 290 int w = crop && maxWidth > 0 ? maxWidth : 263; 291 int h = (maxHeight > 0 ? maxHeight : 100) + 50; 292 new TagWriter(writer).start(Html.DIV) 293 .attribute(Html.COMMON_ID, getId()) 294 .attribute(Html.COMMON_STYLE, 295 "width:" + w + "px;height:" + h + "px") 296 .end(); 297 } 298 299 private int getIntParameter(HttpServletRequest request, String name) { 300 return ServletRequestUtils.getIntParameter(request, name, 0); 301 } 302 303 public void handleContentRequest(HttpServletRequest request, 304 HttpServletResponse response) throws IOException { 305 306 if (isPresent()) { 307 if ("crop".equals(request.getParameter("action"))) { 308 cropImage( 309 getIntParameter(request, "width"), 310 getIntParameter(request, "height"), 311 getIntParameter(request, "x"), 312 getIntParameter(request, "y"), 313 getIntParameter(request, "scaledWidth")); 314 315 response.getWriter().print(getCroppedImageUrl()); 316 } 317 else if ("undo".equals(request.getParameter("action"))) { 318 undoCrop(); 319 } 320 else { 321 ServletUtils.setNoCacheHeaders(response); 322 response.setHeader("Content-Type", getContentType()); 323 response.setContentLength(getSize().intValue()); 324 325 try { 326 FileCopyUtils.copy(new FileInputStream (getFile()), 328 response.getOutputStream()); 329 } 330 catch (IOException e) { 331 if (!SocketException .class.isInstance(e.getCause())) { 333 throw e; 334 } 335 } 336 } 337 } 338 else { 339 response.sendError(HttpServletResponse.SC_NO_CONTENT); 340 } 341 } 342 343 public String getImageUrl() { 344 if (isPresent()) { 345 return getFormContext().getContentUrl(this) 346 + "&time=" + System.currentTimeMillis(); 347 } 348 return null; 349 } 350 351 public String getCropUrl() { 352 if (cropper != null && crop) { 353 return getFormContext().getContentUrl(this) + "&action=crop"; 354 } 355 return null; 356 } 357 358 public String getUndoUrl() { 359 if (cropper != null && crop) { 360 return getFormContext().getContentUrl(this) + "&action=undo"; 361 } 362 return null; 363 } 364 365 public String getCroppedImageUrl() { 366 return getFormContext().getContentUrl(this) 367 + "&cropped=true&time=" + System.currentTimeMillis(); 368 } 369 370 public String getInitScript() { 371 return TemplateUtils.getInitScript(this); 372 } 373 374 public int getMinWidth() { 375 return minWidth; 376 } 377 378 public int getMaxWidth() { 379 return maxWidth; 380 } 381 382 public int getMinHeight() { 383 return minHeight; 384 } 385 386 public int getMaxHeight() { 387 return maxHeight; 388 } 389 390 public int[] getWidths() { 391 return widths; 392 } 393 394 public int[] getHeights() { 395 return heights; 396 } 397 398 } 399 400 } 401 | Popular Tags |