Browse docs
Media Providers
Overview
sky_jobs_base uses one shared media provider for tablet, gallery, camera, CCTV, speedcam, report, and bodycam uploads. FiveManage and Qbox CDN are included. A server resource can register another provider without modifying sky_jobs_base.
| Provider | Browser upload URL | Server-side data URL upload | Delete remote file |
|---|---|---|---|
| FiveManage | Yes | Yes | Yes |
| Qbox CDN | Yes | Yes | Yes |
| Custom adapter | Required for all NUI workflows | Required | Required |
requestUploadUrl must return a temporary browser-safe URL that does not expose those secrets.Select a built-in provider
Configure the provider in sky_jobs_base/config/webhooks.lua, then perform a full server restart.
Webhooks = {
media = {
provider = "fivemanage",
providers = {}
},
fivemanage = {
apiKey = "your_media_api_key_here",
baseUrl = "https://api.fivemanage.com/api/v3/file",
timeoutMs = 10000
}
}
Create a token with the Media permission. See the FiveManage upload guide.
Webhooks = {
media = {
provider = "qbox",
providers = {}
},
qbox = {
apiKey = "qbox_live_abc123",
baseUrl = "https://api.qbox.re/v1/file",
timeoutMs = 10000
}
}
The Qbox key may be stored directly or with the Bearer prefix. See the Qbox CDN documentation.
Register a custom provider
Create a server resource for the adapter and make sky_jobs_base its dependency. Provider names must match ^[a-z][a-z0-9_%-]*$. The built-in names fivemanage and qbox are reserved.
fx_version "cerulean"
game "gta5"
server_script "server.lua"
dependency "sky_jobs_base"
Register the adapter from server.lua:
local function request_upload_url(config, options)
-- Authenticate against your provider on the server and create a
-- temporary browser-safe upload URL.
return true, {
presignedUrl = "https://uploads.example.com/presigned-token",
expiresIn = 300
}
end
local function upload_data_url(config, data_url, options)
-- Decode/upload the data URL through your provider's server API.
return true, {
url = "https://cdn.example.com/example.png",
id = "provider-file-id"
}
end
local function delete_file(config, file_id, options)
-- Delete the provider object identified by file_id.
return true
end
local registration = exports["sky_jobs_base"]:registerMediaProvider("my_provider", {
requestUploadUrl = request_upload_url,
uploadDataUrl = upload_data_url,
deleteFile = delete_file
})
if not registration.success then
error(("Could not register media provider: %s"):format(registration.error))
end
Add its private configuration and select it:
Webhooks = {
media = {
provider = "my_provider",
providers = {
my_provider = {
apiKey = "server-side-secret",
baseUrl = "https://api.example.com/files",
timeoutMs = 10000
}
}
}
}
The adapter receives the my_provider configuration as its first argument. The options table contains trusted server-side options such as filename, path, or an explicitly selected provider.
Adapter contract
Every method returns true, data on success or false, errorCode on failure.
| Method | Success data | Purpose |
|---|---|---|
requestUploadUrl(config, options) | { presignedUrl, expiresIn? } | Creates the browser-safe upload URL used by NUI uploads. |
uploadDataUrl(config, dataUrl, options) | { url, id? } | Uploads base64 data from a trusted server workflow. |
deleteFile(config, fileId, options) | No data required | Deletes the provider object stored under fileId. |
sky_jobs_base validates and normalizes successful results. The selected provider name and timeout are added automatically.
presignedUrl.Server exports
The normalized media operations are also available to trusted server resources:
| Export | Purpose |
|---|---|
getMediaUploadUrl() | Requests an upload URL from the selected provider. |
uploadMediaDataUrl(dataUrl, options?) | Uploads a server-side base64 data URL. |
deleteMediaFile(fileId, options?) | Deletes a remote file. |
registerMediaProvider(name, adapter) | Registers or replaces a custom adapter. |
See Server Exports for return values and examples.
Troubleshooting
media_provider_not_registered: the adapter resource did not start, started beforesky_jobs_base, or used a different provider name.provider_name_reserved: the adapter attempted to register asfivemanageorqbox.missing_adapter_method_*: one of the three required adapter methods is missing.missing_presigned_url:requestUploadUrldid not return a non-emptypresignedUrl.missing_url:uploadDataUrldid not return the final public file URL.
After changing the provider, its configuration, or resource start order, perform a full server restart and test upload plus deletion before players connect.