website/docs/guides/file-association.mdx
File association feature allows you to associate specific file types with your app so that when users open those files, your app is launched to handle them. This can be particularly useful for text editors, image viewers, or any application that works with specific file formats. In this guide, we'll walk through the steps to implement file association in Wails app.
To set up file association, you need to modify your application's wails.json file. In "info" section add a "fileAssociations" section specifying the file types your app should be associated with.
For example:
{
"info": {
"fileAssociations": [
{
"ext": "wails",
"name": "Wails",
"description": "Wails Application File",
"iconName": "wailsFileIcon",
"role": "Editor"
},
{
"ext": "jpg",
"name": "JPEG",
"description": "Image File",
"iconName": "jpegFileIcon",
"role": "Editor"
}
]
}
}
| Property | Description |
|---|---|
| ext | The extension (minus the leading period). e.g. png |
| name | The name. e.g. PNG File |
| iconName | The icon name without extension. Icons should be located in build folder. Proper icons will be generated from .png file for both macOS and Windows |
| description | Windows-only. The description. It is displayed on the Type column on Windows Explorer. |
| role | macOS-only. The app’s role with respect to the type. Corresponds to CFBundleTypeRole. |
When you open file (or files) with your app, the system will launch your app and call the OnFileOpen function in your Wails app. Example:
func main() {
// Create application with options
err := wails.Run(&options.App{
Title: "wails-open-file",
Width: 1024,
Height: 768,
AssetServer: &assetserver.Options{
Assets: assets,
},
BackgroundColour: &options.RGBA{R: 27, G: 38, B: 54, A: 1},
Mac: &mac.Options{
OnFileOpen: func(filePaths []string) { println(filestring) },
},
Bind: []interface{}{
app,
},
})
if err != nil {
println("Error:", err.Error())
}
}
On Windows file association is supported only with NSIS installer. During installation, the installer will create a registry entry for your file associations. When you open file with your app, new instance of app is launched and file path is passed as argument to your app. To handle this you should parse command line arguments in your app. Example:
func main() {
argsWithoutProg := os.Args[1:]
if len(argsWithoutProg) != 0 {
println("launchArgs", argsWithoutProg)
}
}
You also can enable single instance lock for your app. In this case, when you open file with your app, new instance of app is not launched and arguments are passed to already running instance. Check single instance lock guide for details. Example:
func main() {
// Create application with options
err := wails.Run(&options.App{
Title: "wails-open-file",
Width: 1024,
Height: 768,
AssetServer: &assetserver.Options{
Assets: assets,
},
BackgroundColour: &options.RGBA{R: 27, G: 38, B: 54, A: 1},
SingleInstanceLock: &options.SingleInstanceLock{
UniqueId: "e3984e08-28dc-4e3d-b70a-45e961589cdc",
OnSecondInstanceLaunch: app.onSecondInstanceLaunch,
},
Bind: []interface{}{
app,
},
})
}
Currently, Wails doesn't support bundling for Linux. So, you need to create file associations manually. For example if you distribute your app as a .deb package, you can create file associations by adding required files in you bundle. You can use nfpm to create .deb package for your app.
[Desktop Entry]
Categories=Office
Exec=/usr/bin/wails-open-file %u
Icon=wails-open-file.png
Name=wails-open-file
Terminal=false
Type=Application
MimeType=application/x-wails;application/x-test
<?xml version="1.0" encoding="UTF-8"?>
<mime-info xmlns="http://www.freedesktop.org/standards/shared-mime-info">
<mime-type type="application/x-wails">
<comment>Wails Application File</comment>
<glob pattern="*.wails"/>
</mime-type>
</mime-info>
# reload mime types to register file associations
update-mime-database /usr/share/mime
# reload desktop database to load app in list of available
update-desktop-database /usr/share/applications
# update icons
update-icon-caches /usr/share/icons/*
name: "wails-open-file"
arch: "arm64"
platform: "linux"
version: "1.0.0"
section: "default"
priority: "extra"
maintainer: "FooBarCorp <[email protected]>"
description: "Sample Package"
vendor: "FooBarCorp"
homepage: "http://example.com"
license: "MIT"
contents:
- src: ../bin/wails-open-file
dst: /usr/bin/wails-open-file
- src: ./main.desktop
dst: /usr/share/applications/wails-open-file.desktop
- src: ./application-wails-mime.xml
dst: /usr/share/mime/packages/application-x-wails.xml
- src: ./application-test-mime.xml
dst: /usr/share/mime/packages/application-x-test.xml
- src: ../appicon.svg
dst: /usr/share/icons/hicolor/scalable/apps/wails-open-file.svg
- src: ../wailsFileIcon.svg
dst: /usr/share/icons/hicolor/scalable/mimetypes/application-x-wails.svg
- src: ../testFileIcon.svg
dst: /usr/share/icons/hicolor/scalable/mimetypes/application-x-test.svg
# copy icons to Yaru theme as well. For some reason Ubuntu didn't pick up fileicons from hicolor theme
- src: ../appicon.svg
dst: /usr/share/icons/Yaru/scalable/apps/wails-open-file.svg
- src: ../wailsFileIcon.svg
dst: /usr/share/icons/Yaru/scalable/mimetypes/application-x-wails.svg
- src: ../testFileIcon.svg
dst: /usr/share/icons/Yaru/scalable/mimetypes/application-x-test.svg
scripts:
postinstall: ./postInstall.sh
postremove: ./postRemove.sh
nfpm pkg --packager deb --target .
func main() {
argsWithoutProg := os.Args[1:]
if len(argsWithoutProg) != 0 {
println("launchArgs", argsWithoutProg)
}
}
You also can enable single instance lock for your app. In this case, when you open file with your app, new instance of app is not launched and arguments are passed to already running instance. Check single instance lock guide for details. Example:
func main() {
// Create application with options
err := wails.Run(&options.App{
Title: "wails-open-file",
Width: 1024,
Height: 768,
AssetServer: &assetserver.Options{
Assets: assets,
},
BackgroundColour: &options.RGBA{R: 27, G: 38, B: 54, A: 1},
SingleInstanceLock: &options.SingleInstanceLock{
UniqueId: "e3984e08-28dc-4e3d-b70a-45e961589cdc",
OnSecondInstanceLaunch: app.onSecondInstanceLaunch,
},
Bind: []interface{}{
app,
},
})
}