-
Notifications
You must be signed in to change notification settings - Fork 165
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
HTML5 multiple file drag and drop upload component
- Loading branch information
1 parent
0ee6bd0
commit 97cedc8
Showing
9 changed files
with
409 additions
and
0 deletions.
There are no files selected for viewing
2 changes: 2 additions & 0 deletions
2
Frameworks/BusinessLogic/ERAttachment/.settings/org.eclipse.core.resources.prefs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1,4 @@ | ||
eclipse.preferences.version=1 | ||
encoding//Resources/English.lproj/Localizable.strings=UTF-16BE | ||
encoding//Resources/Japanese.lproj/Localizable.strings=UTF-16BE | ||
encoding/<project>=UTF-8 |
32 changes: 32 additions & 0 deletions
32
Frameworks/BusinessLogic/ERAttachment/Components/ERDragAndDropUpload.api
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
<?xml version="1.0" encoding="UTF-8" standalone="no"?> | ||
<wodefinitions> | ||
<wo class="ERDragAndDropUpload.java" wocomponentcontent="true"> | ||
|
||
<binding defaults="Boolean" name="disabled"/> | ||
<binding name="storageType"/> | ||
|
||
<binding name="attachment"/> | ||
<validation message="'attachment' must be bound to a settable value"> | ||
<unsettable name="attachment"/> | ||
</validation> | ||
<validation message="'attachment' is a required binding."> | ||
<unbound name="attachment"/> | ||
</validation> | ||
<binding name="action"/> | ||
<validation message="'action' is a required binding."> | ||
<unbound name="action"/> | ||
</validation> | ||
<binding name="editingContext"/> | ||
<validation message="'editingContext' is a required binding."> | ||
<unbound name="editingContext"/> | ||
</validation> | ||
<binding name="configurationName"/> | ||
<binding name="enterFunction"/> | ||
<binding name="exitFunction"/> | ||
<binding name="overFunction"/> | ||
<binding name="completeFunction"/> | ||
<binding name="completeAllFunction"/> | ||
<binding name="errorFunction"/> | ||
<binding name="accept"/> | ||
</wo> | ||
</wodefinitions> |
4 changes: 4 additions & 0 deletions
4
...rks/BusinessLogic/ERAttachment/Components/ERDragAndDropUpload.wo/ERDragAndDropUpload.html
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
<webobject name = "DropTarget"><webobject name = "Content"/></webobject> | ||
<webobject name = "Enabled"> | ||
<script>dragAndDropUpload('<webobject name = "DropTargetID" />', '<webobject name = "ActionURL" />', <webobject name = "EnterFunction"/>, <webobject name = "ExitFunction"/>, <webobject name = "OverFunction"/>, <webobject name = "CompleteFunction"/>, <webobject name = "CompleteAllFunction"/>, <webobject name = "ErrorFunction"/>);</script> | ||
</webobject> |
53 changes: 53 additions & 0 deletions
53
...orks/BusinessLogic/ERAttachment/Components/ERDragAndDropUpload.wo/ERDragAndDropUpload.wod
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
ActionURL: WOString { | ||
value = postURL; | ||
} | ||
|
||
CompleteAllFunction: WOString { | ||
value = ^completeAllFunction; | ||
valueWhenEmpty = "false"; | ||
} | ||
|
||
CompleteFunction: WOString { | ||
value = ^completeFunction; | ||
valueWhenEmpty = "false"; | ||
} | ||
|
||
Content: WOComponentContent { | ||
|
||
} | ||
|
||
DropTarget: WOGenericContainer { | ||
elementName = "div"; | ||
id = dropTargetID; | ||
class = "dndUpload"; | ||
omitTags = ^disabled; | ||
} | ||
|
||
DropTargetID: WOString { | ||
value = dropTargetID; | ||
} | ||
|
||
Enabled: WOConditional { | ||
condition = ^disabled; | ||
negate = true; | ||
} | ||
|
||
EnterFunction: WOString { | ||
value = ^enterFunction; | ||
valueWhenEmpty = "false"; | ||
} | ||
|
||
ErrorFunction: WOString { | ||
value = ^errorFunction; | ||
valueWhenEmpty = "false"; | ||
} | ||
|
||
ExitFunction: WOString { | ||
value = ^exitFunction; | ||
valueWhenEmpty = "false"; | ||
} | ||
|
||
OverFunction: WOString { | ||
value = ^overFunction; | ||
valueWhenEmpty = "false"; | ||
} |
4 changes: 4 additions & 0 deletions
4
...orks/BusinessLogic/ERAttachment/Components/ERDragAndDropUpload.wo/ERDragAndDropUpload.woo
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
{ | ||
"WebObjects Release" = "WebObjects 5.0"; | ||
encoding = "UTF-8"; | ||
} |
Binary file added
BIN
+108 Bytes
Frameworks/BusinessLogic/ERAttachment/Resources/English.lproj/Localizable.strings
Binary file not shown.
Binary file added
BIN
+90 Bytes
Frameworks/BusinessLogic/ERAttachment/Resources/Japanese.lproj/Localizable.strings
Binary file not shown.
217 changes: 217 additions & 0 deletions
217
...orks/BusinessLogic/ERAttachment/Sources/er/attachment/components/ERDragAndDropUpload.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,217 @@ | ||
package er.attachment.components; | ||
|
||
import java.io.File; | ||
import java.io.FileOutputStream; | ||
import java.io.IOException; | ||
|
||
import org.apache.commons.io.FileUtils; | ||
import org.apache.log4j.Logger; | ||
|
||
import com.webobjects.appserver.WOActionResults; | ||
import com.webobjects.appserver.WOApplication; | ||
import com.webobjects.appserver.WOContext; | ||
import com.webobjects.appserver.WORequest; | ||
import com.webobjects.appserver.WOResponse; | ||
import com.webobjects.eocontrol.EOEditingContext; | ||
import com.webobjects.foundation.NSArray; | ||
import com.webobjects.foundation.NSData; | ||
import com.webobjects.foundation.NSForwardException; | ||
import com.webobjects.foundation.NSPropertyListSerialization; | ||
|
||
import er.attachment.model.ERAttachment; | ||
import er.attachment.model.ERDatabaseAttachment; | ||
import er.attachment.processors.ERAttachmentProcessor; | ||
import er.extensions.appserver.ERXWOContext; | ||
import er.extensions.components.ERXNonSynchronizingComponent; | ||
import er.extensions.eof.ERXQ; | ||
import er.extensions.foundation.ERXArrayUtilities; | ||
import er.extensions.foundation.ERXProperties; | ||
|
||
/** | ||
* A component designed to allow drag and drop uploads of ERAttachments. | ||
* Except where otherwise noted, the javascript functions have a single | ||
* argument: the event. | ||
* | ||
* @binding accept an array of accepted mimetypes. If no mimetypes are specified, all are accepted. ex. (image/png, image/jpg, text/*) | ||
* @binding action the action to fire when an attachment is uploaded | ||
* @binding attachment the uploaded attachment | ||
* @binding completeAllFunction a javascript function to execute when all dropped files are processed | ||
* @binding completeFunction a javascript function to execute after each uploaded file is processed. This function accepts two args. The first is the event. The second is the file. | ||
* @binding configurationName the configuration name. See the package javadocs for more info. | ||
* @binding disabled if true, the upload component is disabled and only displays component content | ||
* @binding editingContext the editing context where the ERAttachments will be created | ||
* @binding enterFunction a javascript function to execute when dragged files enter the drop target | ||
* @binding errorFunction a javascript function to execute when a file upload error occurs. This function accepts two args. The first is the event. The second is the file. | ||
* @binding exitFunction a javascript function to execute when dragged files exit the drop target | ||
* @binding overFunction a javascript function to execute when dragged files are over the drop target | ||
* @binding storageType the ERAttachment storage type (db, file, s3, cf, ...) | ||
* | ||
* @author Ramsey | ||
* | ||
*/ | ||
public class ERDragAndDropUpload extends ERXNonSynchronizingComponent { | ||
/** | ||
* 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 static final Logger log = Logger.getLogger(ERDragAndDropUpload.class); | ||
|
||
private String dropTargetID; | ||
|
||
private boolean invokeAction = false; | ||
|
||
private boolean willAccept = true; | ||
|
||
private NSArray<String> accept; | ||
|
||
public ERDragAndDropUpload(WOContext context) { | ||
super(context); | ||
} | ||
|
||
/** | ||
* @return the dropTargetID | ||
*/ | ||
public String dropTargetID() { | ||
if(dropTargetID == null) { | ||
dropTargetID = ERXWOContext.safeIdentifierName(context(), true); | ||
} | ||
return dropTargetID; | ||
} | ||
|
||
@Override | ||
protected NSArray<String> additionalJavascriptFiles() { | ||
return new NSArray<String>("js/dndupload.js"); | ||
} | ||
|
||
@Override | ||
protected String _frameworkName() { | ||
return "ERAttachment"; | ||
} | ||
|
||
/** | ||
* The ajax request URL for this component. | ||
* @return the post URL for the ajax post request | ||
*/ | ||
public String postURL() { | ||
String key = WOApplication.application().ajaxRequestHandlerKey(); | ||
return context().componentActionURL(key); | ||
} | ||
|
||
@Override | ||
public WOActionResults invokeAction(WORequest request, WOContext context) { | ||
if(invokeAction && willAccept) { | ||
invokeAction = false; | ||
return (WOActionResults) valueForBinding("action"); | ||
} else if (invokeAction) { | ||
invokeAction = false; | ||
willAccept = true; | ||
WOResponse response = new WOResponse(); | ||
//CHECKME 406 or 415? | ||
response.setStatus(400); | ||
response.setContent(localizer().localizedStringForKey("UnacceptableMimetype")); | ||
return response; | ||
} | ||
return super.invokeAction(request, context); | ||
} | ||
|
||
@Override | ||
public void takeValuesFromRequest(WORequest request, WOContext context) { | ||
NSData data = (NSData) request.formValueForKey(dropTargetID()); | ||
if(data != null) { | ||
String mimetype = (String) request.formValueForKey(dropTargetID() + ".mimetype"); | ||
if(!accept().isEmpty() && !acceptMimetype(mimetype)) { | ||
// reject mime types that don't match | ||
invokeAction = true; | ||
willAccept = false; | ||
} else { | ||
String filename = (String) request.formValueForKey(dropTargetID() + ".filename"); | ||
FileOutputStream os = null; | ||
try { | ||
File uploadedFile = File.createTempFile("DragAndDropUpload-", ".tmp"); | ||
os = new FileOutputStream(uploadedFile); | ||
data.writeToStream(os); | ||
ERAttachment upload = ERAttachmentProcessor.processorForType(storageType()).process(editingContext(), uploadedFile, filename, mimetype, storageType(), null); | ||
setValueForBinding(upload, "attachment"); | ||
invokeAction = true; | ||
FileUtils.deleteQuietly(uploadedFile); | ||
} catch (IOException e) { | ||
throw NSForwardException._runtimeExceptionForThrowable(e); | ||
} finally { | ||
if(os != null) { | ||
try { | ||
os.close(); | ||
} catch (IOException e) { | ||
log.error("Error closing file stream", e); | ||
} | ||
} | ||
} | ||
} | ||
} | ||
super.takeValuesFromRequest(request, context); | ||
} | ||
|
||
/** | ||
* The ERAttachment storage type for the uploaded files. | ||
* | ||
* @return the storageType | ||
*/ | ||
public String storageType() { | ||
String key = configurationName() == null | ||
?"er.attachment.storageType" | ||
:"er.attachment." + configurationName() + ".storageType"; | ||
String defaultType = ERXProperties.stringForKeyWithDefault(key, ERDatabaseAttachment.STORAGE_TYPE); | ||
return valueForStringBinding("storageType", defaultType); | ||
} | ||
|
||
/** | ||
* The ERAttachment configuration name for the uploaded files. | ||
* | ||
* @return the configurationName | ||
*/ | ||
public String configurationName() { | ||
return (String) valueForBinding("configurationName"); | ||
} | ||
|
||
/** | ||
* The EOEditingContext where the ERAttachment will be created | ||
*/ | ||
public EOEditingContext editingContext() { | ||
return (EOEditingContext) valueForBinding("editingContext"); | ||
} | ||
|
||
public NSArray<String> accept() { | ||
if(accept == null) { | ||
String acceptString = (String) valueForBinding("accept"); | ||
if(acceptString == null) { | ||
accept = NSArray.emptyArray(); | ||
} else { | ||
// plist deserialization chokes on * | ||
if(acceptString.indexOf('*') > -1) { | ||
acceptString = acceptString.replace("*", ""); | ||
} | ||
accept = NSPropertyListSerialization.arrayForString(acceptString); | ||
} | ||
} | ||
return accept; | ||
} | ||
|
||
//TODO optimize | ||
public boolean acceptMimetype(String mimetype) { | ||
NSArray<String> wildcards = ERXQ.endsWith("toString", "/").filtered(accept()); | ||
for(String wildcard: wildcards) { | ||
if(mimetype.startsWith(wildcard)) { | ||
return true; | ||
} | ||
} | ||
NSArray<String> others = ERXArrayUtilities.arrayMinusArray(accept(), wildcards); | ||
for(String other: others) { | ||
if(mimetype.equals(other)) { | ||
return true; | ||
} | ||
} | ||
return false; | ||
} | ||
} |
Oops, something went wrong.