Every RAP application can host it's own static resources, like documents, scripts, images, or CSS-files. These can then be used
It is not necessary to register images used by CSS theming.
There are multiple ways to register a resource, with the main difference beeing the time and place the registration happens.
application.addResource( "foo/icon.png", new ResourceLoader() { @Override public InputStream getResourceAsStream( String resourceName ) throws IOException { return this.getClass().getClassLoader().getResourceAsStream( "resources/icon.png" ); } } );
<extension point="org.eclipse.rap.ui.resources"> <resource class="my.project.resources.IconResource"> </resource> </extension>
ResourceManager resourceManager = RWT.getResourceManager(); if( !resourceManager.isRegistered( "foo/icon.png" ) ) { InputStream inputStream = this.getClass().getClassLoader().getResourceAsStream( "resources/icon.png" ); try { resourceManager.register( resourceName, inputStream ); } finally { inputStream.close(); } }
Important: To use the resource on the client (e.g. in a browser widget or the JavaScriptLoader), is it necessary to know it's public URL from the clients point of view. (The favicon in the application configuration/branding is an exception, it can use the path given during registration). This information is in all cases provided by the ResourceManager:
String src = RWT.getResourceManager().getLocation( "foo/icon.png" );
If you want to provide downloads in your RAP application, you can use a service handler instead of static resources. Below is an example of a very basic downloads service handler.
public class DownloadServiceHandler implements ServiceHandler { public void service( HttpServletRequest request, HttpServletResponse response ) throws IOException, ServletException { // Which file to download? String fileName = request.getParameter( "filename" ); // Get the file content byte[] download = MyDataStore.getByteArrayData( fileName ); // Send the file in the response response.setContentType( "application/octet-stream" ); response.setContentLength( download.length ); String contentDisposition = "attachment; filename=\"" + fileName + "\""; response.setHeader( "Content-Disposition", contentDisposition ); response.getOutputStream().write( download ); } }
The request has a parameter "filename" which indicates which content
(either static or dynamically generated) should be sent to the client.
The MyDataStore
-line is a placeholder for whatever
code is required to provide the content.
In our example the content is retrieved as byte[]
,
but InputStreams and Readers can be easily accommodated as well.
The service handler has to be registered, like static resources, once per application. The best place to do this is (depending on your application setup) either the Application Configuration or org.eclipse.rap.ui.serviceHandler extension. If need be it can also be done at runtime:
ServiceManager manager = RWT.getServiceManager(); ServiceHandler handler = new DownloadServiceHandler(); manager.registerServiceHandler( "downloadServiceHandler", handler );
The URL for the download link can be generated as follows:
private String createDownloadUrl( String filename ) { StringBuilder url = new StringBuilder(); url.append( RWT.getServiceManager().getServiceHandlerUrl( "downloadServiceHandler" ) ); url.append( '&' ).append( "filename" ).append( '=' ).append( filename ); return url.toString(); }
The link can either be embedded using markup, or opened programmatically with the URLLauncher. The application can not control whether certain file types are opened in a browser popup/tab/window, or in a "save-as" dialog. This is completely up to the browser. However, a markup hyperlink usually has a native context menu with a "save-as" entry.