# PicList Advanced Synchronization Features: Multi-Cloud Config and Gallery Sync

> Discover PicList advanced synchronization features including multi cloud config and gallery sync. Leverage enterprise grade syncing across GitHub Gitee Gitea and WebDAV.

- Repository: [Kuingsmile/piclist](https://github.com/kuingsmile/piclist)
- Tags: deep-dive
- Published: 2026-03-05

---

**PicList provides enterprise-grade synchronization capabilities supporting GitHub, Gitee, Gitea, and WebDAV backends, featuring conflict-aware gallery database merging, proxy support, and incremental configuration uploads through a unified TypeScript API.**

The open-source image hosting tool PicList (kuingsmile/piclist) extends beyond simple uploads by offering robust **advanced synchronization features** that keep your configuration files and gallery databases consistent across multiple machines. Whether you need to sync settings between work and home computers or maintain a centralized gallery database in the cloud, PicList's synchronization subsystem handles complex conflict resolution and network configurations automatically.

## Multi-Backend Cloud Synchronization Architecture

PicList's synchronization engine in [`src/main/utils/syncSettings.ts`](https://github.com/kuingsmile/piclist/blob/main/src/main/utils/syncSettings.ts) abstracts multiple storage providers behind a unified interface, allowing seamless switching between Git-based and WebDAV backends without changing the high-level API.

### Supported Remote Storage Providers

The system currently supports four primary backend types, selected via the `syncConfig.type` property:

- **GitHub**: Uses Octokit with optional `HttpsProxyAgent` for corporate environments
- **Gitee**: Native API integration with Chinese hosting optimization
- **Gitea**: Self-hosted Git platform support
- **WebDAV**: Generic WebDAV endpoints with basic and digest authentication

Each backend implements the four core operations defined in [`syncSettings.ts`](https://github.com/kuingsmile/piclist/blob/main/syncSettings.ts): `uploadLocalToRemote`, `updateLocalToRemote`, `downloadRemoteToLocal`, and `checkCloudFileExist`.

### Core Synchronization Logic in syncSettings.ts

The file [`src/main/utils/syncSettings.ts`](https://github.com/kuingsmile/piclist/blob/main/src/main/utils/syncSettings.ts) contains the primary orchestration logic. Key functions include:

- `getSyncConfig()`: Retrieves user settings from `picgo.getConfig<ISyncConfig>(configPaths.settings.sync)` with sensible defaults
- `isSyncConfigValidate()`: Validates required fields per backend type (e.g., `username`, `repo`, `token` for GitHub)
- `uploadFile()`: Implements incremental logic—first attempting `updateLocalToRemote`, falling back to `uploadLocalToRemote` on 404 errors

## Configuration File Synchronization

PicList treats configuration files ([`data.json`](https://github.com/kuingsmile/piclist/blob/main/data.json), [`manage.json`](https://github.com/kuingsmile/piclist/blob/main/manage.json), etc.) as first-class synchronization citizens, exposing upload and download operations through RPC handlers in [`src/main/events/rpc/routes/setting/configure.ts`](https://github.com/kuingsmile/piclist/blob/main/src/main/events/rpc/routes/setting/configure.ts).

### Uploading Local Configurations

The RPC action `CONFIGURE_UPLOAD_ALL_CONFIG` triggers `uploadFile()` with an array of configuration filenames. This operation:

1. Validates the sync configuration via `isSyncConfigValidate()`
2. Iterates through the file list, calling `uploadFunc` for each
3. Uses the incremental upload strategy (update first, then create)

```typescript
import { uploadFile } from '~/utils/syncSettings';

const files = ['data.json', 'manage.json'];
const uploaded = await uploadFile(files);
console.log(`Uploaded ${uploaded} configuration files`);

```

*Source:* [`src/main/events/rpc/routes/setting/configure.ts`](https://github.com/kuingsmile/piclist/blob/main/src/main/events/rpc/routes/setting/configure.ts) lines 107-112

### Downloading Remote Configurations

Conversely, `CONFIGURE_DOWNLOAD_ALL_CONFIG` invokes `downloadFile()`, which retrieves remote files via `downloadRemoteToLocal()` and writes them to the local data directory. This enables rapid restoration of settings on new machines.

```typescript
import { downloadFile } from '~/utils/syncSettings';

await downloadFile(['data.json', 'manage.json']);

```

*Source:* [`src/main/events/rpc/routes/setting/configure.ts`](https://github.com/kuingsmile/piclist/blob/main/src/main/events/rpc/routes/setting/configure.ts) lines 128-133

## Gallery Database Synchronization with Conflict Resolution

Beyond static configuration files, PicList synchronizes the dynamic gallery database (`gallery.db`), implementing sophisticated merge logic to handle conflicts when the same image metadata exists in both local and remote versions.

### Temporary Workspace Isolation

All gallery sync operations occur within an isolated temporary directory at `$TMPDIR/piclist-sync-tmp`. The system creates three distinct paths:

- `localDBPath`: Copy of the current local database
- `remoteDBPath`: Downloaded remote database
- `dbMerged`: Output path for the merged result

This isolation ensures that failed syncs never corrupt the production database.

### Timestamp-Based Merge Strategy

The `mergeGalleryDB()` function implements conflict resolution by comparing `updatedAt` timestamps:

1. Builds a Map of all gallery items from both local and remote databases
2. For items existing in both locations, selects the version with the newer `updatedAt`
3. Respects `settings.lastSyncTime` to ignore stale remote items that haven't changed since the last synchronization
4. Writes the merged result to `dbMerged` and uploads it back to the remote

```typescript
import { syncGallery } from '~/utils/syncSettings';

const syncedCount = await syncGallery();
console.log(`Synchronized ${syncedCount} gallery databases`);

```

*Source:* [`src/main/utils/syncSettings.ts`](https://github.com/kuingsmile/piclist/blob/main/src/main/utils/syncSettings.ts) lines 82-88 and merge logic at lines 38-66

## Enterprise Features: Proxy and Authentication

PicList's synchronization subsystem includes enterprise-grade networking features for restricted environments and secure authentication.

### Corporate Proxy Support

The system automatically detects and uses proxy settings via `HttpsProxyAgent` for GitHub operations and Axios configurations for WebDAV. The proxy builder in [`src/main/utils/syncSettings.ts`](https://github.com/kuingsmile/piclist/blob/main/src/main/utils/syncSettings.ts) (lines 89-99) constructs the appropriate agent based on user settings, enabling synchronization behind corporate firewalls.

### WebDAV Authentication Methods

For WebDAV backends, PicList supports both **basic** and **digest** authentication via the `AuthType` enum from the `webdav` package. The configuration interface `ISyncConfig` allows specifying `webdavAuthType` to match your server's security requirements.

## Programmatic API Usage

While the PicList UI exposes these features through the settings panel, developers can invoke synchronization directly via the internal API.

### Complete WebDAV Configuration Example

```typescript
import { ISyncConfig } from '~/types/sync';
import { configPaths } from '~/utils/configPaths';

const webdavSync: ISyncConfig = {
  type: 'webdav',
  webdavEndpoint: 'https://webdav.example.com',
  webdavUsername: 'myUser',
  webdavPassword: 'myPass',
  webdavAuthType: 'digest',      // or 'basic'
  webdavSslEnabled: true,
  webdavSavePath: '/piclist-sync',
  proxy: '',                     // optional proxy URL
};

picgo.setConfig({ [configPaths.settings.sync]: webdavSync });

```

*Source:* Configuration schema defined in [`src/renderer/utils/configPaths.ts`](https://github.com/kuingsmile/piclist/blob/main/src/renderer/utils/configPaths.ts) lines 57-58

### Batch Configuration Synchronization

```typescript
import { uploadFile, downloadFile } from '~/utils/syncSettings';

// Upload multiple config files
const uploadResult = await uploadFile(['data.json', 'manage.json', 'settings.json']);

// Download to restore on new machine
await downloadFile(['data.json', 'manage.json']);

```

## Summary

PicList's **advanced synchronization features** provide production-ready capabilities for maintaining consistency across multiple environments:

- **Multi-backend support** for GitHub, Gitee, Gitea, and WebDAV with unified API abstractions in [`src/main/utils/syncSettings.ts`](https://github.com/kuingsmile/piclist/blob/main/src/main/utils/syncSettings.ts)
- **Intelligent conflict resolution** for gallery databases using timestamp-based merging and `lastSyncTime` tracking
- **Isolated temporary workspaces** at `$TMPDIR/piclist-sync-tmp` ensuring safe database operations
- **Enterprise networking** with `HttpsProxyAgent` support and both basic/digest WebDAV authentication
- **Incremental upload strategy** that updates existing remote files before falling back to creation
- **Programmatic accessibility** through RPC routes and direct TypeScript API imports

## Frequently Asked Questions

### How does PicList handle conflicts when syncing the gallery database across multiple devices?

PicList implements timestamp-based conflict resolution in the `mergeGalleryDB()` function within [`src/main/utils/syncSettings.ts`](https://github.com/kuingsmile/piclist/blob/main/src/main/utils/syncSettings.ts). When merging local and remote databases, it builds a Map of all gallery items and compares their `updatedAt` timestamps, keeping the newer version. It also respects the `settings.lastSyncTime` property to ignore stale remote items that haven't changed since the last synchronization, ensuring the most recent metadata prevails.

### What cloud storage providers does PicList support for configuration synchronization?

According to the source code in [`src/main/utils/syncSettings.ts`](https://github.com/kuingsmile/piclist/blob/main/src/main/utils/syncSettings.ts), PicList supports four primary backend types: **GitHub** (via Octokit), **Gitee**, **Gitea** (self-hosted), and **WebDAV** (generic). The system uses a switch statement on `syncConfig.type` to determine which implementation of `uploadLocalToRemote`, `downloadRemoteToLocal`, and other operations to invoke, allowing seamless backend swapping without changing the high-level API.

### Can PicList synchronize settings behind a corporate firewall or proxy?

Yes, PicList includes enterprise proxy support for all synchronization operations. The [`src/main/utils/syncSettings.ts`](https://github.com/kuingsmile/piclist/blob/main/src/main/utils/syncSettings.ts) file implements proxy handling using `HttpsProxyAgent` for GitHub API requests and Axios configurations for WebDAV connections. Users can specify a proxy URL in the sync configuration, enabling synchronization from restricted network environments. Additionally, WebDAV authentication supports both basic and digest methods to comply with various corporate security policies.

### Is it possible to trigger PicList synchronization programmatically rather than through the GUI?

Absolutely. While the PicList UI exposes sync controls, developers can invoke synchronization directly through the internal TypeScript API. The [`src/main/utils/syncSettings.ts`](https://github.com/kuingsmile/piclist/blob/main/src/main/utils/syncSettings.ts) module exports functions like `syncGallery()`, `uploadFile()`, and `downloadFile()` that can be imported and called programmatically. Additionally, the RPC routes in [`src/main/events/rpc/routes/setting/configure.ts`](https://github.com/kuingsmile/piclist/blob/main/src/main/events/rpc/routes/setting/configure.ts) expose these capabilities to renderer processes, enabling custom scripts and plugins to trigger configuration uploads, downloads, and gallery merges without user interaction.