A browser-based file transfer server for your Apple app.
Give users a simple way to move files between a computer and your app over Wi-Fi—without a cable, account, or cloud service. Start the server, show its local address, and open that address in a browser.
Built on SwiftyUploader and Apple's SwiftNIO, with the browser interface from GCDWebUploader. This is an independent project, not an official Swift port or a drop-in replacement for GCDWebServer. The public Swift module and class names remain
SwiftyUploader.
- A bundled browser interface: upload, download, browse, rename, delete, and create folders.
- A configurable shared directory—expose an import folder instead of your entire Documents directory.
- Customizable page titles, instructions, button text, and footer.
- Swift Package Manager integration, with no Objective-C bridging required.
- A SwiftUI demo and regression tests for file operations and HTTP handling.
The browser assets are served by the app. No CDN connection is needed to load the interface.
The English browser interface, running with sample files. Branding and text are configurable.
In Xcode, choose File → Add Package Dependencies and enter:
https://github.com/MeloDreek/GCDWebServer_Swift.git
Select the SwiftyUploader library product. For another Swift package:
dependencies: [
.package(url: "https://github.com/MeloDreek/GCDWebServer_Swift.git", from: "1.0.0")
],
targets: [
.target(
name: "YourApp",
dependencies: [.product(name: "SwiftyUploader", package: "GCDWebServer_Swift")]
)
]The package declares iOS 14+ and macOS 11+ support, including Mac Catalyst. Use a current Xcode toolchain compatible with your resolved SwiftNIO version. It is not a watchOS server, WebDAV implementation, or general-purpose GCDWebServer compatibility layer.
import Foundation
import SwiftyUploader
final class WiFiTransferSession {
// Retain the server for the lifetime of the transfer screen.
private let uploader: SwiftyUploader
init() throws {
let documents = try FileManager.default.url(
for: .documentDirectory, in: .userDomainMask,
appropriateFor: nil, create: true
)
uploader = SwiftyUploader(documents.appendingPathComponent("WiFi Imports"))
}
func start() { uploader.run() }
// Starting is asynchronous. Refresh your UI once the server is listening.
var browserAddress: String { uploader.getIPAddress() }
func stop() { uploader.stop() }
}getIPAddress() returns a complete URL, including http:// and the port when needed. Do not prepend another scheme. An empty string means no usable address was found; it is not proof that local-network permission was granted. The convenience lookup uses the en0 IPv4 interface, so some Mac Ethernet/VPN configurations may require displaying the appropriate interface address with getPort() yourself.
Keep the app in the foreground during transfers and stop the server when the transfer screen closes. SwiftyUploader() with no argument shares the app's Documents directory. Prefer an explicit, dedicated folder.
Set configuration before starting the server:
var config = SwiftyUploaderConfig()
config.header = "Wi-Fi Transfer"
config.title = "Your Music Library"
config.message = "Drop your audio files here to import them."
config.footer = "Keep this screen open until your transfers finish."
config.uploadFiles = "Upload Files"
config.createFolder = "New Folder"
config.showCreateFolder = true
SwiftyUploader.config = configPass your own localized strings for each field. Each server captures its own shared folder, but page configuration is process-wide: configure it before starting and do not mutate it during transfers. message and footer accept trusted HTML; never insert untrusted filenames or user input into them. showCreateFolder controls the browser UI only; it is not an authorization policy.
Add a clear NSLocalNetworkUsageDescription to the host app's Info.plist:
<key>NSLocalNetworkUsageDescription</key>
<string>Transfer files between this app and your browser over your local network.</string>For a sandboxed macOS app, enable Incoming Connections (Server) in App Sandbox. iOS does not keep this server running indefinitely in the background. Both devices must be on a network that allows direct connections; guest Wi-Fi isolation and firewalls can block access.
Use only on a trusted local network, explicitly enabled by the user. This server has no authentication or TLS. Anyone who can reach its port can read, upload, modify, or delete files inside the shared directory. Do not forward the port to the Internet, expose sensitive directories, or treat a hidden browser button as access control.
The library confines requested paths to the shared directory and rejects symbolic links within it, but is not a security boundary against another local process modifying the filesystem concurrently. Keep the exposed folder under your app's control. Add authentication and transport security in an appropriate server architecture if your use case requires them.
For security reports, see SECURITY.md. Never attach private documents, credentials, or real user data to an issue.
Open SwiftyUploaderDemo/SwiftyUploaderDemo.xcodeproj. It references the package in the repository root. Choose your own signing team for a physical device.
Run package tests on macOS:
swift testBug reports and focused pull requests are welcome. Include the platform, Swift/Xcode version, a minimal reproduction, and synthetic test files. If the project saves you time, a star helps other developers discover it.
- kejinlu/SwiftyUploader: original Swift server and demo, MIT licensed.
- swisspol/GCDWebServer: GCDWebUploader browser interface, BSD-3-Clause licensed.
- apple/swift-nio: networking foundation, Apache-2.0 licensed.
Swift code and original contributions to this fork are available under the MIT license. Bundled browser components retain their own licenses; see THIRD_PARTY_NOTICES.md. Upstream attribution and history are preserved.
