Fileupload"

From Documentation
 
(32 intermediate revisions by 7 users not shown)
Line 3: Line 3:
 
= Fileupload =
 
= Fileupload =
  
*Demonstration:  [http://www.zkoss.org/zkdemo/userguide/#u1 FileUpload ]
+
*Demonstration:  [http://www.zkoss.org/zkdemo/file_handling/file_upload File Upload ]
 
*Java API: <javadoc>org.zkoss.zul.Fileupload</javadoc>
 
*Java API: <javadoc>org.zkoss.zul.Fileupload</javadoc>
 
*JavaScript API: <javadoc directory="jsdoc">zul.wgt.Fileupload</javadoc>
 
*JavaScript API: <javadoc directory="jsdoc">zul.wgt.Fileupload</javadoc>
 +
*Style Guide: N/A
  
 
= Employment/Purpose =
 
= Employment/Purpose =
  
There are two ways to use <javadoc>org.zkoss.zul.Fileupload</javadoc>: uses <javadoc>org.zkoss.zul.Fileupload</javadoc> as a component to upload files, or invoke <javadoc method="get()">org.zkoss.zul.Fileupload</javadoc> to open a dialog to upload files.
+
There are two ways to use <javadoc>org.zkoss.zul.Fileupload</javadoc> as a component to upload files, or invoke <javadoc method="get()">org.zkoss.zul.Fileupload</javadoc> to open a dialog to upload files.
  
== Use as a Component ==
+
= Use as a Component =
  
 
<javadoc>org.zkoss.zul.Fileupload</javadoc> itself is a component. You can use it directly as follows.
 
<javadoc>org.zkoss.zul.Fileupload</javadoc> itself is a component. You can use it directly as follows.
Line 17: Line 18:
 
<source lang="xml">
 
<source lang="xml">
 
<fileupload label="Upload">
 
<fileupload label="Upload">
   <attribute name="onLoad">
+
   <attribute name="onUpload">
 
   org.zkoss.util.media.Media media = event.getMedia();
 
   org.zkoss.util.media.Media media = event.getMedia();
 
   //then, you can process media here
 
   //then, you can process media here
 
   </attribute>
 
   </attribute>
</button>
+
</fileupload>
 
</source>
 
</source>
  
Line 31: Line 32:
 
</source>
 
</source>
  
== Invoke the Static Method: get ==
+
Please refer to [[ZK Component Reference/Essential Components/Button#Upload|Button: Upload]] for details.
  
Fileupload provides a set of static methods to simplify the file uploading, such as <javadoc method="get()">org.zkoss.zul.Fileupload</javadoc>, <javadoc method="get(java.lang.String, java.lang.String)">org.zkoss.zul.Fileupload</javadoc>, and so on.
+
= Invoke the Static Method: get =
 +
 
 +
Fileupload provides a set of static methods to simplify file uploading, such as <javadoc method="get()">org.zkoss.zul.Fileupload</javadoc>, <javadoc method="get(java.lang.String, java.lang.String)">org.zkoss.zul.Fileupload</javadoc>, and so on.
  
 
The behavior is a little bit different depending on if the event thread is enabled (default: it is disabled<ref>Prior to 5.0, it is default to enabled. Refer to [[ZK_Configuration_Reference/zk.xml/The_system-config_Element#The_disable-event-thread_Element | ZK Configuration Reference: disable-event-thread]].</ref>).
 
The behavior is a little bit different depending on if the event thread is enabled (default: it is disabled<ref>Prior to 5.0, it is default to enabled. Refer to [[ZK_Configuration_Reference/zk.xml/The_system-config_Element#The_disable-event-thread_Element | ZK Configuration Reference: disable-event-thread]].</ref>).
Line 42: Line 45:
 
</blockquote>
 
</blockquote>
  
=== Event Thread Disabled ===
+
== Creating a custom template for the Static  Method: get ==
 +
 
 +
When using the static method Fileupload.get(...) to display a generic upload popup, the popup content is defined by a ZUL file, so you could customize it by replacing it with your own implementation. It can be done easily by invoking <javadoc method="setTemplate(java.lang.String)">org.zkoss.zul.Fileupload</javadoc>. Notice that it affects all Fileupload popups subsequently created in an application. It is typically called when the application starts (i.e., in <javadoc method="init(org.zkoss.zk.ui.WebApp)" type="interface">org.zkoss.zk.ui.util.WebAppInit</javadoc> -- for more information, please refer to [[ZK Developer's Reference/Customization/Life Cycle Listener|ZK Developer's Reference: Life Cycle Listener]]).
 +
 
 +
To implement a custom template, please take a look at [https://github.com/zkoss/zk/blob/master/zul/src/archive/web/zul/html/fileuploaddlg.zul the default template].
 +
 
 +
== Example Usage ==
  
When the event thread is disabled (default), the execution won't be suspended when <javadoc method="get()">org.zkoss.zul.Fileupload</javadoc> is called. In other words, the returned value is always null. To retrieve the uploaded files, the developer has to listen the <tt>onUpload</tt> event, which is sent when the uploading is completed.
+
When the event thread is disabled (default), the execution won't be suspended when <javadoc method="get()">org.zkoss.zul.Fileupload</javadoc> is called. In other words, the returned value is always null. To retrieve the uploaded files, the developer has to listen the <code>onUpload</code> event, which is sent when the uploading is completed.
  
By default, the <tt>onUpload</tt> event is sent to all root components. For example, <javadoc>org.zkoss.zul.Div</javadoc> will, in the following example, receive the <tt>onUpload</tt> event.
+
By default, the <code>onUpload</code> event is sent to all root components. For example, <javadoc>org.zkoss.zul.Div</javadoc> will, in the following example, receive the <code>onUpload</code> event since it is the root component:
  
 
<source lang="xml">
 
<source lang="xml">
Line 74: Line 83:
 
</source>
 
</source>
  
If you prefer to send the event to a particular component, you have to specify it in the desktop attribute called <tt>org.zkoss.zul.Fileupload.target</tt>. For example,
 
  
<source lang="java">
+
=== Specify the Callback Event Listener ===
  desktop.setAttribute("org.zkoss.zul.Fileupload.target", uploadHandler);
+
 
    //assume uploadHandler is a component
+
{{versionSince| 6.5.3}}
 +
 
 +
If you prefer the event being sent to the callback event listener, specify the event listener when invoke Fileupload.get().
 +
 
 +
'''Note''': the target of the upload event is always null.
 +
 
 +
For example:
 +
 
 +
<source lang="xml" highlight="5, 24">
 +
<zk>
 +
    <vbox>
 +
      <button label="Upload">
 +
            <attribute name="onClick">
 +
                Fileupload.get(new EventListener(){
 +
                    public void onEvent(UploadEvent event) {
 +
                        org.zkoss.util.media.Media media = event.getMedia();
 +
                        if (media instanceof org.zkoss.image.Image) {
 +
                            org.zkoss.image.Image img = (org.zkoss.image.Image) media;
 +
                            if (img.getWidth() > img.getHeight()){
 +
                                if (img.getHeight() > 300) {
 +
                                    pics.setHeight("300px");
 +
                                    pics.setWidth(img.getWidth() * 300 / img.getHeight() + "px");
 +
                                }
 +
                            }
 +
                            if (img.getHeight() > img.getWidth()){
 +
                                if (img.getWidth() > 400) {
 +
                                    pics.setWidth("400px");
 +
                                    pics.setHeight(img.getHeight() * 400 / img.getWidth() + "px");
 +
                                }
 +
                            }
 +
                            image.setContent(img);
 +
                        } else {
 +
                            Messagebox.show("Not an image: "+media, "Error", Messagebox.OK, Messagebox.ERROR);
 +
                        }
 +
                    }
 +
                })
 +
            </attribute>
 +
        </button>
 +
        <image id="image" />
 +
    </vbox>
 +
</zk>
 
</source>
 
</source>
  
=== Event Thread Enabled ===
+
=== Specify the Target Component ===
 +
 
 +
{{versionSince| 5.0.2}}
 +
 
 +
If you prefer the event being sent to a particular component, specify the component in the desktop's attribute called
 +
<code>org.zkoss.zul.Fileupload.target</code>.
  
== Specify the target component ==
+
For example, we could have the button to receive the onUpload event as follows:
  
Since 5.0.2, if the event thread is disabled, an onUpload event is posted to all root components when the upload dialog is closed.
+
<source lang="xml" highlight="5, 24">
 +
<zk>
 +
    <zscript deferred="true"><![CDATA[
 +
    import org.zkoss.util.media.Media;
 +
 
 +
    Executions.getCurrent().getDesktop().setAttribute(
 +
            "org.zkoss.zul.Fileupload.target", uploadBtn);
 +
 
 +
    public void processMedia(Media[] media) {
 +
        if (media != null) {
 +
            for (int i = 0; i < media.length; i++) {
 +
                if (media[i] instanceof org.zkoss.image.Image) {
 +
                    image.setContent(media[i]);
 +
                } else {
 +
                    Messagebox.show("Not an image: " + media[i], "Error",
 +
                            Messagebox.OK, Messagebox.ERROR);
 +
                    break; //not to show too many errors
 +
                }
 +
            }
 +
        }
 +
    }
 +
]]></zscript>
 +
    <vbox>
 +
        <button id="uploadBtn" label="Upload"
 +
            onUpload="processMedia(event.getMedias());"
 +
            onClick="Fileupload.get(-1);" />
 +
        <image id="image" />
 +
    </vbox>
 +
</zk>
 +
</source>
  
If you want the event being sent to a particular component, specify the component in the desktop's attribute called
+
== Event Thread Enabled (deprecated)==
<code>org.zkoss.zul.Fileupload.target</code>.
 
  
For example,
+
If the event thread is enable, the uploaded file will be returned directly by <javadoc method="get()">org.zkoss.zul.Fileupload</javadoc> and other static methods, such as:
  
<source lang="java">
+
<source lang="xml">
desktop.setAttribute("org.zkoss.zul.Fileupload.target", mainWindow);
+
<zk>
Fileupload.get(); //then mainWindow will receive the onUpload event
+
<button label="Upload">
 +
<attribute name="onClick">{
 +
org.zkoss.util.media.Media[] media = Fileupload.get(-1);
 +
if (media != null) {
 +
for (int i = 0; i &lt; media.length; i++) {
 +
if (media[i] instanceof org.zkoss.image.Image) {
 +
org.zkoss.zul.Image image = new org.zkoss.zul.Image();
 +
image.setContent(media[i]);
 +
image.setParent(pics);
 +
} else {
 +
Messagebox.show("Not an image: "+media[i], "Error", Messagebox.OK, Messagebox.ERROR);
 +
break; //not to show too many errors
 +
}
 +
}
 +
}
 +
}</attribute>
 +
</button>
 +
<vbox id="pics" />
 +
</zk>
 
</source>
 
</source>
 +
 +
As shown, <javadoc method="get(int)">org.zkoss.zul.Fileupload</javadoc> won't return until the end user uploads the files (and/or closes the dialog).
 +
 +
= Temporary File Created During Uploading =
 +
This component depends on Apache Commons Fileupload ([https://commons.apache.org/proper/commons-fileupload/apidocs/org/apache/commons/fileupload/disk/DiskFileItemFactory.html DiskFileItemFactory]), so <code>org.apache.commons.io.FileCleanerTracker</code> will delete those temporary files created during uploading. Please refer to [https://commons.apache.org/proper/commons-fileupload/using.html Resource cleanup]
 +
 +
You can verify this cleanup by enforcing garbage collecting with JVisualVM.
  
 
= Example =
 
= Example =
  
 +
Here is an example that uses <javadoc>org.zkoss.zul.Fileupload</javadoc> as a component:
  
 
<source lang="xml" >
 
<source lang="xml" >
 
<image id="img" />
 
<image id="img" />
 
Upload your hot shot:
 
Upload your hot shot:
<fileupload onUpload="img.setContent(event.media)" />
+
<fileupload label="Upload" onUpload="img.setContent(event.media)" />
 
</source>
 
</source>
  
 +
=Supported Events=
  
=Supported events=
+
{| class='wikitable' | width="100%"
 
 
{| border="1" | width="100%"
 
 
! <center>Name</center>
 
! <center>Name</center>
 
! <center>Event Type</center>
 
! <center>Event Type</center>
Line 116: Line 222:
 
| None
 
| None
 
|}
 
|}
 +
*Inherited Supported Events: [[ZK_Component_Reference/Essential_Components/Button#Supported_Events | Button]]
  
 
=Supported Children=
 
=Supported Children=
Line 121: Line 228:
 
  *NONE
 
  *NONE
  
=Use cases=
+
=Use Cases=
  
{| border='1px' | width="100%"
+
{| class='wikitable' | width="100%"
 
! Version !! Description !! Example Location
 
! Version !! Description !! Example Location
 
|-
 
|-
Line 132: Line 239:
  
 
=Version History=
 
=Version History=
 
+
{{LastUpdated}}
{| border='1px' | width="100%"
+
{| class='wikitable' | width="100%"
 
! Version !! Date !! Content
 
! Version !! Date !! Content
 
|-
 
|-

Latest revision as of 07:49, 4 July 2022

Fileupload

Employment/Purpose

There are two ways to use Fileupload as a component to upload files, or invoke Fileupload.get() to open a dialog to upload files.

Use as a Component

Fileupload itself is a component. You can use it directly as follows.

<fileupload label="Upload">
   <attribute name="onUpload">
   org.zkoss.util.media.Media media = event.getMedia();
   //then, you can process media here
   </attribute>
</fileupload>

Fileupload is actually a button with upload=true. In other words, the above is equivalent to

<button label="Upload" upload="true">
...

Please refer to Button: Upload for details.

Invoke the Static Method: get

Fileupload provides a set of static methods to simplify file uploading, such as Fileupload.get(), Fileupload.get(String, String), and so on.

The behavior is a little bit different depending on if the event thread is enabled (default: it is disabled[1]).


  1. Prior to 5.0, it is default to enabled. Refer to ZK Configuration Reference: disable-event-thread.

Creating a custom template for the Static Method: get

When using the static method Fileupload.get(...) to display a generic upload popup, the popup content is defined by a ZUL file, so you could customize it by replacing it with your own implementation. It can be done easily by invoking Fileupload.setTemplate(String). Notice that it affects all Fileupload popups subsequently created in an application. It is typically called when the application starts (i.e., in WebAppInit.init(WebApp) -- for more information, please refer to ZK Developer's Reference: Life Cycle Listener).

To implement a custom template, please take a look at the default template.

Example Usage

When the event thread is disabled (default), the execution won't be suspended when Fileupload.get() is called. In other words, the returned value is always null. To retrieve the uploaded files, the developer has to listen the onUpload event, which is sent when the uploading is completed.

By default, the onUpload event is sent to all root components. For example, Div will, in the following example, receive the onUpload event since it is the root component:

<div onUpload="processMedia(event.getMedias());">
    <zscript deferred="true"><![CDATA[
    import org.zkoss.util.media.Media;
 
    public void processMedia(Media[] media) {
        if (media != null) {
            for (int i = 0; i < media.length; i++) {
                if (media[i] instanceof org.zkoss.image.Image) {
                    image.setContent(media[i]);
                } else {
                    Messagebox.show("Not an image: " + media[i], "Error",
                            Messagebox.OK, Messagebox.ERROR);
                    break; //not to show too many errors
                }
            }
        }
    }
]]></zscript>
    <vbox>
        <button label="Upload" onClick="Fileupload.get(-1);" />
        <image id="image" />
    </vbox>
</div>


Specify the Callback Event Listener

Since 6.5.3

If you prefer the event being sent to the callback event listener, specify the event listener when invoke Fileupload.get().

Note: the target of the upload event is always null.

For example:

<zk>
    <vbox>
       <button label="Upload">
            <attribute name="onClick">
                Fileupload.get(new EventListener(){
                    public void onEvent(UploadEvent event) {
                        org.zkoss.util.media.Media media = event.getMedia();
                        if (media instanceof org.zkoss.image.Image) {
                            org.zkoss.image.Image img = (org.zkoss.image.Image) media;
                            if (img.getWidth() > img.getHeight()){
                                if (img.getHeight() > 300) {
                                    pics.setHeight("300px");
                                    pics.setWidth(img.getWidth() * 300 / img.getHeight() + "px");
                                }
                            }
                            if (img.getHeight() > img.getWidth()){
                                if (img.getWidth() > 400) {
                                    pics.setWidth("400px");
                                    pics.setHeight(img.getHeight() * 400 / img.getWidth() + "px");
                                }
                            }
                            image.setContent(img);
                        } else {
                            Messagebox.show("Not an image: "+media, "Error", Messagebox.OK, Messagebox.ERROR);
                        }
                    }
                })
            </attribute>
        </button>
        <image id="image" />
    </vbox>
</zk>

Specify the Target Component

Since 5.0.2

If you prefer the event being sent to a particular component, specify the component in the desktop's attribute called org.zkoss.zul.Fileupload.target.

For example, we could have the button to receive the onUpload event as follows:

<zk>
    <zscript deferred="true"><![CDATA[
    import org.zkoss.util.media.Media;

    Executions.getCurrent().getDesktop().setAttribute(
            "org.zkoss.zul.Fileupload.target", uploadBtn);

    public void processMedia(Media[] media) {
        if (media != null) {
            for (int i = 0; i < media.length; i++) {
                if (media[i] instanceof org.zkoss.image.Image) {
                    image.setContent(media[i]);
                } else {
                    Messagebox.show("Not an image: " + media[i], "Error",
                            Messagebox.OK, Messagebox.ERROR);
                    break; //not to show too many errors
                }
            }
        }
    }
]]></zscript>
    <vbox>
        <button id="uploadBtn" label="Upload"
            onUpload="processMedia(event.getMedias());"
            onClick="Fileupload.get(-1);" />
        <image id="image" />
    </vbox>
</zk>

Event Thread Enabled (deprecated)

If the event thread is enable, the uploaded file will be returned directly by Fileupload.get() and other static methods, such as:

<zk>
	<button label="Upload">
	<attribute name="onClick">{
		org.zkoss.util.media.Media[] media = Fileupload.get(-1);
		if (media != null) {
			for (int i = 0; i &lt; media.length; i++) {
				if (media[i] instanceof org.zkoss.image.Image) {
					org.zkoss.zul.Image image = new org.zkoss.zul.Image();
					image.setContent(media[i]);
					image.setParent(pics);
				} else {
					Messagebox.show("Not an image: "+media[i], "Error", Messagebox.OK, Messagebox.ERROR);
					break; //not to show too many errors
				}
			}
		}
	}</attribute>
	</button>
	<vbox id="pics" />
</zk>

As shown, Fileupload.get(int) won't return until the end user uploads the files (and/or closes the dialog).

Temporary File Created During Uploading

This component depends on Apache Commons Fileupload (DiskFileItemFactory), so org.apache.commons.io.FileCleanerTracker will delete those temporary files created during uploading. Please refer to Resource cleanup

You can verify this cleanup by enforcing garbage collecting with JVisualVM.

Example

Here is an example that uses Fileupload as a component:

<image id="img" />
Upload your hot shot:
<fileupload label="Upload" onUpload="img.setContent(event.media)" />

Supported Events

Name
Event Type
None None

Supported Children

*NONE

Use Cases

Version Description Example Location
     

Version History

Last Update : 2022/07/04


Version Date Content
5.0.2 May 2010 Able to specify a target for the onUpload event sent by Fileupload.get(). Used if the event thread is disabled.



Last Update : 2022/07/04

Copyright © Potix Corporation. This article is licensed under GNU Free Documentation License.