package er.attachment.components; import java.io.File; import java.io.IOException; import java.net.MalformedURLException; import com.webobjects.appserver.WOActionResults; import com.webobjects.appserver.WOComponent; import com.webobjects.appserver.WOContext; import com.webobjects.appserver.WORequest; import com.webobjects.eocontrol.EOEditingContext; import com.webobjects.foundation.NSForwardException; import er.attachment.model.ERAttachment; import er.attachment.model.ERDatabaseAttachment; import er.attachment.processors.ERAttachmentProcessor; import er.extensions.components.ERXComponentUtilities; import er.extensions.foundation.ERXFileUtilities; import er.extensions.foundation.ERXProperties; import er.extensions.foundation.ERXValueUtilities; /** * <p> * ERAttachmentUpload provides a very simple wrapper around either a WOFileUpload * or an AjaxFileUpload component (depending on the value of the "ajax" binding). * When the upload is successfully completed, this component will automatically * process the attachment. It is not necessary to use this component -- it's * only to make the process slightly easier. If you want to use your own * existing file upload setup, in your completion action, you can simply call: * </p> * * <code> * ERAttachment attachment = ERAttachmentProcessor.processorForType(storageType).process(editingContext, fileUploadFinalFilePath, fileUploadFilePath, mimeType, configurationName, ownerID); * </code> * * <p> * Note that for the attachment binding, you do not create the attachment instance and * pass it in. The attachment processor inside of ERAttachmentUpload creates an appropriate * attachment instance for you (using the editing context you provide) and simply binds it * back to you when the upload is complete. * </p> * * @author mschrag * @binding attachment the binding to store the newly created attachment in * @binding editingContext the editing context to create the attachment in * @binding storageType the type of attachment to create, i.e. "s3", "db", or "file" -- defaults to "db" (or the value of er.attachment.storageType) * @binding mimeType (optional) the mime type of the upload (will be guessed by extension if not set) * @binding ajax (optional) if true, AjaxFileUpload is used, if false WOFileUpload is used * @binding configurationName (optional) the configuration name for this attachment (see top level documentation) * @binding ownerID (optional) a string ID of the "owner" of this attachment (Person.primaryKey for instance) * @binding width (optional) the desired width of the attachment * @binding height (optional) the desired height of the attachment * @binding others all AjaxFileUpload bindings are proxied * @binding cleanup (optional) if true, the old attachment binding value will be deleted * @binding class (optional) the class attribute of the file input * @binding style (optional) the style attribute of the file input * * @property er.attachment.[configurationName].tempFolder the temp folder to use for WOFileUploads for a specific configuration. Default is er.attachment.tempFolder value. * @property er.attachment.tempFolder the temp folder to use for WOFileUploads. If not set, temporary dir will be set from File.createTempFile(). * @property er.attachment.[configurationName].storageType * @property er.attachment.storageType * @property er.attachment.[configurationName].width * @property er.attachment.width * @property er.attachment.[configurationName].height * @property er.attachment.height * */ public class ERAttachmentUpload extends WOComponent { /** * Do I need to update serialVersionUID? * See section 5.6 <cite>Type Changes Affecting Serialization</cite> on page 51 of the * <a href="http://java.sun.com/j2se/1.4/pdf/serial-spec.pdf">Java Object Serialization Spec</a> */ private static final long serialVersionUID = 1L; private String _filePath; private String _finalFilePath; public ERAttachmentUpload(WOContext context) { super(context); } public void setFilePath(String filePath) { _filePath = filePath; } public String filePath() { return _filePath; } public void setFinalFilePath(String finalFilePath) { _finalFilePath = finalFilePath; } public String finalFilePath() { return _finalFilePath; } @Override public boolean synchronizesVariablesWithBindings() { return false; } public boolean ajax() { return ERXComponentUtilities.booleanValueForBinding(this, "ajax"); } @Override public WOActionResults invokeAction(WORequest request, WOContext context) { WOActionResults results = super.invokeAction(request, context); if (context.wasFormSubmitted() && !ajax()) { try { _uploadSucceeded(); valueForBinding("succeededAction"); } catch (IOException e) { throw new NSForwardException(e, "Failed to process uploaded attachment."); } } return results; } public String tempFilePath() throws IOException { String configurationName = (String) valueForBinding("configurationName"); String tempFolderPath = ERXProperties.stringForKey("er.attachment." + configurationName + ".tempFolder"); if (tempFolderPath == null) { tempFolderPath = ERXProperties.stringForKey("er.attachment.tempFolder"); } String fileExtension = ERXFileUtilities.fileExtension(_filePath); if (fileExtension == null) { fileExtension = "tmp"; } fileExtension = "." + fileExtension; File tempFile; if (tempFolderPath != null) { File tempFolder = new File(tempFolderPath); tempFile = File.createTempFile("ERAttachmentUpload-", fileExtension, tempFolder); } else { tempFile = File.createTempFile("ERAttachmentUpload-", fileExtension); } return tempFile.getAbsolutePath(); } public ERAttachment _uploadSucceeded() throws IOException { if (_finalFilePath == null) { return null; } String configurationName = (String) valueForBinding("configurationName"); String storageType = (String) valueForBinding("storageType"); if (storageType == null) { storageType = ERXProperties.stringForKey("er.attachment." + configurationName + ".storageType"); if (storageType == null) { storageType = ERXProperties.stringForKeyWithDefault("er.attachment.storageType", ERDatabaseAttachment.STORAGE_TYPE); } } EOEditingContext editingContext = (EOEditingContext) valueForBinding("editingContext"); File uploadedFile = new File(_finalFilePath); String mimeType = (String) valueForBinding("mimeType"); String ownerID = (String) valueForBinding("ownerID"); int width = ERXValueUtilities.intValueWithDefault(valueForBinding("width"), -1); if (width == -1) { width = ERXProperties.intForKeyWithDefault("er.attachment." + configurationName + ".width", -1); if (width == -1) { width = ERXProperties.intForKeyWithDefault("er.attachment.width", -1); } } int height = ERXValueUtilities.intValueWithDefault(valueForBinding("height"), -1); if (height == -1) { height = ERXProperties.intForKeyWithDefault("er.attachment." + configurationName + ".height", -1); if (height == -1) { height = ERXProperties.intForKeyWithDefault("er.attachment.height", -1); } } ERAttachment attachment = ERAttachmentProcessor.processorForType(storageType).process(editingContext, uploadedFile, _filePath, mimeType, width, height, configurationName, ownerID); if (ERXComponentUtilities.booleanValueForBinding(this, "cleanup", false)) { ERAttachment oldAttachment = (ERAttachment) valueForBinding("attachment"); if (oldAttachment != null) { oldAttachment.delete(); } } setValueForBinding(attachment, "attachment"); return attachment; } public WOActionResults uploadSucceeded() throws MalformedURLException, IOException { _uploadSucceeded(); return (WOActionResults) valueForBinding("succeededAction"); } }