File types restrictions
Due to security reasons it is sometimes necessary to restrict specific file types when uploading.
Following customization in index.html shows how to handle file extensions:
injector.services.files.manager.getAcceptFilter = function(fileChooserName, filter) {
    if (fileChooserName === 'uploadFC') {
        return "image/png";
    }
    return filter;
};
injector.services.files.manager.validateUploadedFile = function(file) {
    if (file.name.endsWith(".png") || file.type === 'image/png') {
        return { valid: true };
    }
    return { valid: false, error: "Cannot upload file - " + file.name };
};
Drag & Drop
Webswing supports drag & drop functionality between swing components, drag & drop upload to file chooser and direct drag & drop of file from local system to swing component.
File chooser upload
To upload a file using drag & drop to a file chooser, simply open file chooser and drop a file from local file system to the marked area. Note that transparentFileSave config should be false.

Direct drag & drop
To use direct drag & drop you first need to register a swing component that should receive the uploaded file. Use WebswingApi method to do this:
if (WebswingUtil.isWebswing()) {
    WebswingApi api = WebswingUtil.getWebswingApi();
    api.registerDropComponent(pic1);
}
The registered component must have a valid TransferHandler:
pic1.setTransferHandler(picHandler);
This is an example of a simple TransferHandler:
class PictureTransferHandler extends TransferHandler {
    private static List<DataFlavor> supportedFlavors = Arrays.asList(DataFlavor.javaFileListFlavor);
    public boolean importData(JComponent c, Transferable t) {
        if (canImport(c, t.getTransferDataFlavors())) {
            if (t.isDataFlavorSupported(DataFlavor.javaFileListFlavor)) {
                try {
                    List<File> fileList = (List<File>) t.getTransferData(DataFlavor.javaFileListFlavor);
                    if (fileList != null && !fileList.isEmpty()) {
                        File droppedFile = fileList.get(0);
                        return true;
                    }
                } catch (IOException | UnsupportedFlavorException e) {
                    // log
                }
            }
        }
        return false;
    }
    public boolean canImport(JComponent c, DataFlavor[] flavors) {
        for (int i = 0; i < flavors.length; i++) {
            if (supportedFlavors.contains(flavors[i])) {
                return true;
            }
        }
        return false;
    }
}

File viewers
In webswing config you can configure a mapping of file extension to URL handler for specific AWT Desktop file operation.

In the configuration above, files with txt extension are handled with /txt-viewer URL handler when Desktop.getDesktop().open(), Desktop.getDesktop().edit() or Desktop.getDesktop().print() is called for the file. If you want to use the browser's default action use ${file} as URL value.
You can implement a URL handler by creating a folder with index.html inside application web folder:

This is an example code for a simple file viewer:
<!DOCTYPE html>
<html>
    <head>
        <title>Demo text file viewer</title>
        <meta charset="utf-8">
        <script language="javascript" type="text/javascript">
            const searchParams = new URLSearchParams(window.location.search);
            const blobId = searchParams.get('file');
            console.log("blobId", blobId)
        
            document.addEventListener("DOMContentLoaded", function(event) {
                var fileContent = document.getElementById('filecontent');
                fileContent.value = 'Loading file content ...';
                
                fetch(blobId)
                  .then(response => response.blob())
                  .then(blob => {
                    const reader = new FileReader();
                    reader.readAsText(blob);
                    reader.onloadend = function() {
                      fileContent.value = reader.result;
                    };
                  })
                  .catch(error => {
                      fileContent.value = "Blob error " + error
                      console.error('blob error', error)
                  });
            });
        </script>
    </head>
    <body>
        <h1>Text file viewer</h1>
        <textarea id="filecontent" rows="20" cols="110" style="white-space: pre" readonly></textarea>
    </body>
</html>