You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

advanced-dragndrop.asciidoc 27KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506
  1. ---
  2. title: Drag and Drop
  3. order: 12
  4. layout: page
  5. ---
  6. [[advanced.dragndrop]]
  7. = Drag and Drop
  8. ((("Drag and Drop", id="term.advanced.dragndrop", range="startofrange")))
  9. Dragging an object from one location to another by grabbing it with mouse,
  10. holding the mouse button pressed, and then releasing the button to "drop" it to
  11. the other location is a common way to move, copy, or associate objects. For
  12. example, most operating systems allow dragging and dropping files between
  13. folders or dragging a document on a program to open it. Framework version 8.1 adds support for https://developer.mozilla.org/en-US/docs/Web/API/HTML_Drag_and_Drop_API[HTML5 drag and drop] features. This makes it possible to set components as drag sources that user can drag and drop, or to set them as drop targets to drop things on.
  14. == Drag Source
  15. Any component can be made a drag source that has textual data that is transferred when it is dragged and dropped.
  16. To make a component a drag source, you apply the [classname]#DragSourceExtension# to it. Then you can define the text to transfer, and the allowed drag effect.
  17. [source, java]
  18. ----
  19. Label draggableLabel = new Label("You can grab and drag me");
  20. DragSourceExtension<Label> dragSource = new DragSourceExtension<>(draggableLabel);
  21. // set the allowed effect
  22. dragSource.setEffectAllowed(EffectAllowed.MOVE);
  23. // set the text to transfer
  24. dragSource.setDataTransferText("hello receiver");
  25. // set other data to transfer (in this case HTML)
  26. dragSource.setDataTransferData("text/html", "<label>hello receiver</label>");
  27. ----
  28. The __effect allowed__ specifies the allowed effects that must match the __drop effect__ of the drop target. If these don't match, the drop event is never fired on the target. If multiple effects are allowed, the user can use the modifier keys to switch between the desired effects. The default effect and the modifier keys are system and browser dependent.
  29. The __data transfer text__ is textual data, that the drop target will receive in the __drop event__.
  30. The __data transfer data__ is any data of the given type, that the drop target will also receive in the __drop event__. The order, in which the data is set for the drag source, is preserved, which helps the drop target finding the most preferred and supported data.
  31. [NOTE]
  32. ====
  33. Note that `"text"` is the only cross browser supported data type. If your application supports IE11, pleas only use the `setDataTransferText()` method.
  34. ====
  35. The [classname]#DragStartEvent# is fired when the drag has started, and the [classname]#DragEndEvent# event when the drag has ended, either in a drop or a cancel.
  36. [source, java]
  37. ----
  38. dragSource.addDragStartListener(event ->
  39. Notification.show("Drag event started")
  40. );
  41. dragSource.addDragEndListener(event -> {
  42. if (event.isCanceled()) {
  43. Notification.show("Drag event was canceled");
  44. } else {
  45. Notification.show("Drag event finished");
  46. }
  47. });
  48. ----
  49. You can check whether the drag was canceled using the `isCanceled()` method.
  50. It is possible to transfer any Object as server side data to the drop target if both the drag source and drop target are placed in the same UI. This data is available in the drop event via the `DropEvent.getDragData()` method.
  51. [source, java]
  52. ----
  53. dragSource.addDragStartListener(event ->
  54. dragSource.setDragData(myObject)
  55. );
  56. dragSource.addDragEndListener(event ->
  57. dragSource.setDragData(null)
  58. );
  59. ----
  60. === CSS Style Rules
  61. The drag source element, additional to it's primary style name, have a style name with the `-dragsource` suffix. For example, a Label component would have the style name `v-label-dragsource` when the drag source extension is applied to it.
  62. Additionally, the elements also have the `v-draggable` style name that is independent of the component's primary style.
  63. While being dragged, the element also gets the style name with suffix `-dragged`.
  64. An example for this is `v-label-dragged` in case of a Label component.
  65. This style name is added during the drag start and removed during the drag end event.
  66. The browsers allow the user to select and drag and drop text, which could cause issues with components that have text. The Framework tries to prevent this by automatically adding the following style to all `v-draggable` elements. It is included by the sass mixin `valo-drag-element`.
  67. [source, css]
  68. ----
  69. .v-draggable {
  70. -moz-user-select: none !important;
  71. -ms-user-select: none !important;
  72. -webkit-user-select: none !important;
  73. user-select: none !important;
  74. }
  75. ----
  76. [[advanced.dragndrop.drophandler]]
  77. == Drop Target
  78. The drag operations end when the mouse button is released on a valid drop target. It is then up to the target to react to the drop event and the data associated with the drag, set by the drag source.
  79. To make a component be a drop target, you apply the [classname]#DropTargetExtension# to it. The extension allows you to control when the drop is acceptable and then react to the drop event.
  80. [source, java]
  81. ----
  82. VerticalLayout dropTargetLayout = new VerticalLayout();
  83. dropTargetLayout.setCaption("Drop things inside me");
  84. dropTargetLayout.addStyleName(ValoTheme.LAYOUT_CARD);
  85. // make the layout accept drops
  86. DropTargetExtension<VerticalLayout> dropTarget = new DropTargetExtension<>(dropTargetLayout);
  87. // the drop effect must match the allowed effect in the drag source for a successful drop
  88. dropTarget.setDropEffect(DropEffect.MOVE);
  89. // catch the drops
  90. dropTarget.addDropListener(event -> {
  91. // if the drag source is in the same UI as the target
  92. Optional<AbstractComponent> dragSource = event.getDragSourceComponent();
  93. if (dragSource.isPresent() && dragSource.get() instanceof Label) {
  94. // move the label to the layout
  95. dropTargetLayout.addComponent(dragSource.get());
  96. // get possible transfer data
  97. String message = event.getDataTransferData("text/html");
  98. if (message != null) {
  99. Notification.show("DropEvent with data transfer html: " + message);
  100. } else {
  101. // get transfer text
  102. message = event.getDataTransferText();
  103. Notification.show("DropEvent with data transfer text: " + message);
  104. }
  105. // handle possible server side drag data, if the drag source was in the same UI
  106. event.getDragData().ifPresent(data -> handleMyDragData((MyObject) data));
  107. }
  108. });
  109. ----
  110. When data is dragged over a drop target, the __v-drag-over__ class name is applied to the root element of the drop target component automatically.
  111. === Controlling When The Drop is Acceptable
  112. The __drop effect__ allows you to specify the desired drop effect, and for a succesful drop it must match the allowed effect that has been set for the drag source. Note that you can allow multiple effects, and that you should not rely on the default effect since it may vary between browsers.
  113. The __drop criteria__ allows you to determine whether the current drag data can be dropped on the drop target. It is executed on `dragenter`, `dragover` and `drop` events. The script gets the current event as a parameter named `event`. Returning `false` will prevent the drop and no drop event is fired on the server side.
  114. ////
  115. TODO Add an example of drop criteria
  116. ////
  117. === CSS Style Rules
  118. Each drop target element have an applied style name, the primary style name with `-droptarget` suffix, e.g. `v-label-droptarget`, to indicate that it is a potential target for data to be dropped onto it.
  119. When dragging data over a drop target and the drag over criteria passes, a style name is applied to indicate that the element accepts the drop. This style name is the primary style name with `-drag-center` suffix, e.g. `v-label-drag-center`.
  120. ////
  121. TODO add back when supported with new API ?
  122. [[advanced.dragndrop.external]]
  123. == Dragging Files from Outside the Browser
  124. The [classname]#DropTargetExtension# allows dragging files from outside the
  125. browser and dropping them on a target component.
  126. Dropped files are automatically uploaded to the application and can be acquired from the
  127. wrapper with [methodname]#getFiles()#. The files are represented as
  128. [classname]#Html5File# objects as defined in the inner class. You can define an
  129. upload [classname]#Receiver# to receive the content of a file to an
  130. [classname]#OutputStream#.
  131. Dragging and dropping files to browser is supported in HTML 5 and requires a
  132. compatible browser, such as Mozilla Firefox 3.6 or newer.
  133. ////
  134. [[advanced.dragndrop.mobile]]
  135. == Mobile Drag And Drop Support
  136. The HTML 5 Drag and Drop API is not yet supported by mobile browsers. To enable HTML5 DnD support on mobile devices, we have included
  137. an link:https://github.com/timruffles/mobile-drag-drop[external Polyfill]. Please note that this Polyfill is under the BSD 2 License.
  138. By default, the mobile DnD support is disabled, but you can enable it any time for a [classname]#UI#. Starting from the request where the support was enabled, all the added [classname]#DragSourceExtension#, [classname]#DropTargetExtension# and their subclasses will also work on mobile devices for that UI. The Polyfill is only loaded when the user is using a touch device.
  139. Drag and Drop is mutually exclusive with context click on mobile devices.
  140. [source, java]
  141. ----
  142. public class MyUI extends UI {
  143. protected void init(VaadinRequest request) {
  144. setMobileHtml5DndEnabled(true);
  145. }
  146. }
  147. ----
  148. [NOTE]
  149. ====
  150. When disabling the support, you need to also remove all the [classname]#DragSourceExtension#, [classname]#DropTargetExtension# and their subclasses that were added when the mobile DnD support was enabled.
  151. ====
  152. === CSS Style Rules
  153. The Polyfill allows you to apply custom styling to enhance the user experience on touch devices. It is important to remember that these customizations are only used when the polyfill is loaded, and not possible for desktop DnD operations.
  154. The drag image can be customized using the `dnd-poly-drag-image` class name. You must NOT wrap the class rule with e.g. `.valo`, since that is not applied to the drag image element. The following styling can be used to make the drag image opaque and "snap back" when the user did not drop to a valid dropzone:
  155. [source, css]
  156. ====
  157. .dnd-poly-drag-image {
  158. opacity: .5 !important;
  159. }
  160. .dnd-poly-drag-image.dnd-poly-snapback {
  161. transition-property: transform, -webkit-transform !important;
  162. transition-duration: 200ms !important;
  163. transition-timing-function: ease-out !important;
  164. }
  165. ====
  166. More details can be found from the link:https://github.com/timruffles/ios-html5-drag-drop-shim/tree/rewrite:[Polyfill] website.
  167. [[advanced.dragndrop.grid]]
  168. == Drag and Drop Rows in Grid
  169. It is possible to drag and drop the rows of a Grid component. This allows reordering of rows, dragging rows between different Grids, dragging rows outside of a Grid or dropping data onto rows.
  170. In Vaadin Framework 8.2, a `GridRowDragger` helper has been added to make it easier for the simple cases to enable drag-and-drop support for reordering one grid's rows and moving rows between two grids with the same data type.
  171. === Drag and Drop Reordering Items of a Grid (since 8.2)
  172. To allow the user to reorder the rows in a grid, you can use the `GridRowDragger` extension. It will handle configuring the grid as a drag source and drop target, and insert the dropped rows to the dropped index in the data provider, when a `ListDataProvider` is used.
  173. [source,java]
  174. ----
  175. // create a new grid backed by a list data provider
  176. Grid<Task> taskGrid = new Grid<>("Priority Tasks", service.getTasks());
  177. // grid column etc. setup omitted
  178. // enable DnD reordering within the grid
  179. GridRowDragger<Task> gridRowDragger = new GridRowDragger<>(taskGrid);
  180. // disable all columns sorting so DnD reordering is always used
  181. grid.getColumns().stream().forEach(col -> col.setSortable(false));
  182. ----
  183. The `GridRowDragger` uses the `DropMode.BETWEEN` by default. It does not allow the user to drop data on top of a sorted grid's rows by automatically switching to `DropMode.ON_GRID` if the grid has been sorted by the user. This is because the shown drop location would not be correct due to the sorting. It is recommended that you disable the sorting for the grid, by using the `Column.setSortable` method (like above). By default, all columns are sortable when a in-memory data provider is used. If you allow the user to drop on top of a sorted grid's rows, you should scroll the dropped data to be visible with `grid.scrollToRow(index);` after drop for good UX - the `GridRowDragger` does not do this!
  184. If you want to customize the setup for the grid as a drag source or drop target, you can access and customize the handlers with the `getGridDragSource()` and `getGridDropTarget()` methods.
  185. For supporting other data providers, you can customize data provider updating on drop event with `setSourceDataProviderUpdater(SourceDataProviderUpdater<T> updater)` (for the source grid row removal) and `setTargetDataProviderUpdater(TargetDataProviderUpdater<T> updater)` (for the target grid row adding). The drop index calculation can be customized via `setDropIndexCalculator(DropIndexCalculator<T> dropIndexCalculator)`.
  186. === Drag and Drop between two Grids (since 8.2)
  187. The `GridRowDragger` extension enables you to easily setup drag and drop moving of data between two grids. The same features apply as with the single grid reordering case in previous chapter.
  188. The following code snippet shows an example of allowing dragging items both ways between two grids. Note that it does not allow the user to drop the data on the same grid where the drag was started from, by setting the drop effect to `NONE` and thus the drop indicator is not shown.
  189. [source,java]
  190. ----
  191. // create grids with list data providers, and disable sorting
  192. Grid<Person> left = createGrid();
  193. Grid<Person> right = createGrid();
  194. GridRowDragger<Person> leftToRight = new GridRowDragger<>(left, right);
  195. GridRowDragger<Person> rightToLeft = new GridRowDragger<>(right, left);
  196. // Don't show the drop indicator for drags over the same grid where the drag started
  197. leftToRight.getGridDragSource()
  198. .addDragStartListener(event -> rightToLeft.getGridDropTarget()
  199. .setDropEffect(DropEffect.NONE));
  200. leftToRight.getGridDragSource().addDragEndListener(
  201. event -> rightToLeft.getGridDropTarget().setDropEffect(null));
  202. rightToLeft.getGridDragSource()
  203. .addDragStartListener(event -> leftToRight.getGridDropTarget()
  204. .setDropEffect(DropEffect.NONE));
  205. rightToLeft.getGridDragSource().addDragEndListener(
  206. event -> leftToRight.getGridDropTarget().setDropEffect(null));
  207. ----
  208. === Grid as a Drag Source
  209. A Grid component's rows can be made draggable by applying [classname]#GridDragSource# extension to the component. The extended Grid's rows become draggable, meaning that each row can be grabbed and moved by the mouse individually.
  210. When the Grid's selection mode is `SelectionMode.MULTI` and multiple rows are selected, it is possible to drag all the visible selected rows by grabbing one of them. However, when the grabbed row is not selected, only that one row will be dragged.
  211. [NOTE]
  212. ====
  213. It is important to note that when dragging multiple rows, only the visible selected rows will be set as dragged data.
  214. ====
  215. By default, the drag data of type `"text"` will contain the content of each column separated by a tabulator character (`"\t"`).
  216. When multiple rows are dragged, the generated data is combined into one String separated by new line characters (`"\n"`).
  217. You can override the default behaviour and provide a custom drag data for each item by setting a custom _drag data generator_ for the `"text"` type.
  218. The generator is executed for each item and returns a `String` containing the data to be transferred for that item.
  219. The following example shows how you can define the allowed drag effect and customize the drag data by setting a drag data generator.
  220. [source,java]
  221. ----
  222. Grid<Person> grid = new Grid<>();
  223. // ...
  224. GridDragSource<Person> dragSource = new GridDragSource<>(grid);
  225. // set allowed effects
  226. dragSource.setEffectAllowed(EffectAllowed.MOVE);
  227. // add a drag data generator
  228. dragSource.setDragDataGenerator("text", person -> {
  229. return person.getFirstName() + " " + person.getLastName() +
  230. "\t" + // tabulator character
  231. person.getAddress().getCity();
  232. });
  233. ----
  234. It is possible to set multiple generators with the `setDragDataGenerator(type, generator)` method.
  235. The generated data will be set as data transfer data with the given type and can then be accessed during drop from the drop event's `getDataTransferData(type)` method.
  236. The [classname]#GridDragStartEvent# is fired when dragging a row has started, and the [classname]#GridDragEndEvent# when the drag has ended, either in a drop or a cancel.
  237. [source,java]
  238. ----
  239. dragSource.addGridDragStartListener(event ->
  240. // Keep reference to the dragged items
  241. draggedItems = event.getDraggedItems()
  242. );
  243. // Add drag end listener
  244. dragSource.addGridDragEndListener(event -> {
  245. // If drop was successful, remove dragged items from source Grid
  246. if (event.getDropEffect() == DropEffect.MOVE) {
  247. ((ListDataProvider<Person>) grid.getDataProvider()).getItems()
  248. .removeAll(draggedItems);
  249. grid.getDataProvider().refreshAll();
  250. // Remove reference to dragged items
  251. draggedItems = null;
  252. }
  253. });
  254. ----
  255. The dragged rows can be accessed from both events using the `getDraggedItems()` method.
  256. ==== CSS Style Rules
  257. A drag source Grid's rows have the `v-grid-row-dragsource` and the `v-draggable` style names applied to indicate that the rows are draggable.
  258. Additionally, the style name `v-grid-row-dragged` is applied to all the dragged rows during the drag start event and removed during the drag end event.
  259. === Grid as a Drop Target
  260. To make a Grid component's rows accept a drop event, apply the [classname]#GridDropTarget# extension to the component. When creating the extension, you need to specify where the transferred data can be dropped on.
  261. [NOTE]
  262. ====
  263. Since 8.2, there is an option to make the grid not accept drops on rows if the grid has been sorted by the user. This is because the drop location might not be in the place that is shown to the users due to the sorting – and this can cause bad user experience. This is controlled with the method `setDropAllowedOnSortedGridRows` and is by default set to `true` to not change behavior in comparison to Framework version 8.1. When this is set to `false` and the user has sorted the grid, there will not be a target drop row for drops for the grid, and the indicator is always the same as with `DropMode.ON_GRID`.
  264. When the grid has been sorted, you should put the dropped data to the correct location (according to the sorting), and then scroll to the row where the dropped data ended up into and possibly also selecting it.
  265. ====
  266. [source,java]
  267. ----
  268. Grid<Person> grid = new Grid<>();
  269. // ...
  270. GridDropTarget<Person> dropTarget = new GridDropTarget<>(grid, DropMode.BETWEEN);
  271. dropTarget.setDropEffect(DropEffect.MOVE);
  272. // do not show drop target between rows when grid has been sorted
  273. dropTarget.setDropAllowedOnSortedGridRows(false);
  274. ----
  275. The _drop mode_ specifies the behaviour of the row when an element is dragged over or dropped onto it. Use `DropMode.ON_TOP` when you want to drop elements on top of a row and `DropMode.BETWEEN` when you want to drop elements between rows. `DropMode_ON_TOP_OR_BETWEEN` allows to drop on between or top rows. `DropMode.ON_GRID` (since version 8.2) does not allow dropping on the grid rows, but just into the grid, without a specific target row.
  276. The [classname]#GridDropEvent# is fired when data is dropped onto one of the Grid's rows. The following example shows how you can insert items into the Grid at the drop position. If the drag source is another Grid, you can access the generated drag data with the event's [methodname]#getDataTransferText()# method.
  277. If the drag source Grid uses a custom generator for a different type than `"text"`, you can access it's generated data using the [methodname]#getDataTransferData(type)# method. You can also check all the received data transfer data by fetching the type-to-data map with the [methodname]#getDataTransferData()# method.
  278. [source,java]
  279. ----
  280. dropTarget.addGridDropListener(event -> {
  281. // Accepting dragged items from another Grid in the same UI
  282. event.getDragSourceExtension().ifPresent(source -> {
  283. if (source instanceof GridDragSource) {
  284. // Get the target Grid's items
  285. ListDataProvider<Person> dataProvider = (ListDataProvider<Person>)
  286. event.getComponent().getDataProvider();
  287. List<Person> items = (List<Person>) dataProvider.getItems();
  288. // Calculate the target row's index
  289. int index = items.size();
  290. if (event.getDropTargetRow().isPresent()) {
  291. index = items.indexOf(event.getDropTargetRow().get()) + (
  292. event.getDropLocation() == DropLocation.BELOW ? 1 : 0);
  293. }
  294. // Add dragged items to the target Grid
  295. items.addAll(index, draggedItems);
  296. dataProvider.refreshAll();
  297. // Show the dropped data
  298. Notification.show("Dropped row data: " + event.getDataTransferText());
  299. }
  300. });
  301. });
  302. ----
  303. The _drop location_ property in the [classname]#GridDropEvent# specifies the dropped location in relative to grid row the drop happened on and depends on the used [classname]#DropMode#. When the drop happened on top of a row, the possible options for the location are `ON_TOP`, `ABOVE` and `BELOW`.
  304. If the grid is empty or if the drop was on empty space after the last row in grid, and the [classname]#DropMode.ON_TOP# was used, then the drop location `EMPTY` will be used. If the drop modes [classname]#DropMode.BETWEEN# or [classname]#DropMode.ON_TOP_OR_BETWEEN# are used, then the location can be `EMPTY` only when the grid was empty; otherwise the drop happened `BELOW` the last visible row. When the drop location is `EMPTY`, the [methodname]#getDropTargetRow# method will also return an empty optional. If the grid has been sorted by the user and `setDropAllowedOnSortedGridRows` has been set to `false`, the location will be `EMPTY` and there will not be a target row for the drops.
  305. When dropping on top of the grid's header or footer, the drop location will be `EMPTY` if there are no rows in the grid or if [classname]#DropMode.ON_TOP# was used. If there are rows in the grid, dropping on top of the header will set the drop location to `ABOVE` and the dropped row will be the first currently visible row in grid. Similarly, if dropping on top of the footer, the drop location will be `BELOW` and the dropped row will be the last visible row in the grid.
  306. ==== CSS Style Rules
  307. A drop target Grid's body has the style name `v-grid-body-droptarget` to indicate that it is a potential target for data to be dropped.
  308. When dragging data over a drop target Grid's row, depending on the drop mode and the mouse position relative to the row, a style name is applied to the row or to the grid body to indicate the drop location.
  309. When dragging on top of a row, `v-grid-row-drag-center` indicates ON_TOP, `v-grid-row-drag-top` indicates ABOVE and `v-grid-row-drag-bottom` indicates BELOW locations. When dragging on top of an empty grid, or when the drop location is ON_TOP and dragged below the last row in grid (and there is empty space visible), the `v-grid-body-drag-top` style is applied to the `v-grid-tablewrapper` element which surrounds the grid header, body and footer.
  310. (((range="endofrange", startref="term.advanced.dragndrop")))
  311. === Drag and Drop Rows in TreeGrid
  312. To make the rows of a TreeGrid component draggable or to make them a drop target, apply [classname]#TreeGridDragSource# or [classname]#TreeGridDropTarget# extensions to the component, respectively.
  313. In addition to the drag and drop features for Grid above, [classname]#TreeGridDropEvent# provides information about the status of the node (expanded or collapsed) and its depth in the hierarchy.
  314. == Drag and Drop Files
  315. Files can be uploaded to the server by dropping them onto a file drop target. To make a component a file drop target, apply the [classname]#FileDropTarget# extension to it by creating a new instance and passing the component as first constructor parameter to it.
  316. You can handle the dropped files with the `FileDropHandler` that you add as the second constructor parameter. The [classname]#FileDropEvent#, received by the handler, contains information about the dropped files such as file name, file size and mime type.
  317. In the handler you can decide if you would like to upload each of the dropped files.
  318. To start uploading a file, set a `StreamVariable` to it. The stream variable provides an output stream where the file will be written and has callback methods for all the stages of the upload process.
  319. [source,java]
  320. ----
  321. Label dropArea = new Label("Drop files here");
  322. FileDropTarget<Label> dropTarget = new FileDropTarget<>(dropArea, event -> {
  323. Collection<Html5File> files = event.getFiles();
  324. files.forEach(file -> {
  325. // Max 1 MB files are uploaded
  326. if (file.getFileSize() <= 1024 * 1024) {
  327. file.setStreamVariable(new StreamVariable() {
  328. // Output stream to write the file to
  329. @Override
  330. public OutputStream getOutputStream() {
  331. try{
  332. return new FileOutputStream("/path/to/files/"
  333. + file.getFileName());
  334. }catch (FileNotFoundException e) {
  335. e.printStackTrace();
  336. }
  337. return null;
  338. }
  339. // Returns whether onProgress() is called during upload
  340. @Override
  341. public boolean listenProgress() {
  342. return true;
  343. }
  344. // Called periodically during upload
  345. @Override
  346. public void onProgress(StreamingProgressEvent event) {
  347. Notification.show("Progress, bytesReceived="
  348. + event.getBytesReceived());
  349. }
  350. // Called when upload started
  351. @Override
  352. public void streamingStarted(StreamingStartEvent event) {
  353. Notification.show("Stream started, fileName="
  354. + event.getFileName());
  355. }
  356. // Called when upload finished
  357. @Override
  358. public void streamingFinished(StreamingEndEvent event) {
  359. Notification.show("Stream finished, fileName="
  360. + event.getFileName());
  361. }
  362. // Called when upload failed
  363. @Override
  364. public void streamingFailed(StreamingErrorEvent event) {
  365. Notification.show("Stream failed, fileName="
  366. + event.getFileName());
  367. }
  368. @Override
  369. public boolean isInterrupted() {
  370. return false;
  371. }
  372. });
  373. }
  374. }
  375. });
  376. ----