About ZenSync

ZenSync is a tool to help move your photos from your computer to Zenfolio.  It is run from the command-line and syncronizes your photo collection each time it is run. Zensync goes down an entire directory and uploads only those photos that are not already on Zenfolio.  It doesn’t matter how you organize your photos — they just need to be in a single directory tree.  If you are hosting your own photos, using Gallery, or Coppermine, this would be a great tool to help transition to Zenfolio.

 Folder & Zenfolio

It is written in PHP5, and can run on any operating system that has PHP5 installed.  It has been tested on Ubuntu Linux, and should not require any non-standard modules installed to run it.  The code should be pretty easy to follow and modify.

Code Output 

Optionally, it will use ImageMagick’s ‘convert’ command to convert PhotoCD images to JPEG’s, and FFMPEG to create Video thumbnails of AVI files it encounters.

Get the code here: Zensync.tgz

This entry was posted in Uncategorized. Bookmark the permalink.

41 Responses to About ZenSync

  1. Lee Havens says:


    Downloaded files on to my PC and run WinZip to extract files. I am using Vista Premium. Could you please advise next step?



  2. oli says:


    When I run the code it says the class SoapClient can’t be found.. what library are you using?

    It’s not really true to say it works on “any machine with php5” if it relies on this 3rd party library 😀



  3. oli says:

    Hi, me again!

    My fault!

    If you’re wanting to use this on Windows make sure that you’ve got php_soap.dll, put it in your extensions folder and include it with your php.ini in the Extensions section. (it wasn’t there by default on the version I had).

    To run it, edit the zensync.php file to match your login details and, from a command line, do :

    path\to\php.exe -c “path\to\php.ini” “path\to\zensync.php”

    Sorry about the confusion, I googled but could only find Zend and 3rd party soap libraries, none of which had a constructor that matched yours.

    Thanks a lot for the app – does exactly what I wanted 😀


  4. Prasad says:

    Thanks for making this script available. Just what I was looking for. I am running this on Mac OS X and it makes sync’ing between my desktop and zenfolio super easy.

    Here are a couple of things I noticed I thought I will mention..

    a) If you have a space character in the photo file name, the upload would fail with “Bad request” error. I found that it was because the filename is not urlencoded in line 150, dirclass.inc. I changed this to do a urlencode() and that fixes the issue.

    b) My local directory structure looks something like Group Name\Gallery Name\Photo. If I had a “-” in any of the group names, upload would create a new gallery with the same group name except replacing the “-” with a single quote ‘. For eg, San-Francisco would become San’Francisco. So I did a search and replace on the code wherever this substitution was done, and then got things back to working again.

    Hope this helps. And thanks again for the script!

    Would love to see someday, if we can automate the script to add photos to a preset of collections as they’re uploaded.


  5. admin says:

    a) If you have a space character in the photo file name, the upload would fail with “Bad request” error. I found that it was because the filename is not urlencoded in line 150, dirclass.inc. I changed this to do a urlencode() and that fixes the issue.

    Thanks for the catch! I’ll fix it and get it in the code!

    b) My local directory structure looks something like Group Name\Gallery Name\Photo. If I had a “-” in any of the group names, upload would create a new gallery with the same group name except replacing the “-” with a single quote ‘. For eg, San-Francisco would become San’Francisco. So I did a search and replace on the code wherever this substitution was done, and then got things back to working again.

    Yeah.. that’s one of the “benefits” of writing your own code – I had changed all my “‘” directories to “-” years ago for some reason.. Linux didn’t like having single quotes in file names or something, so all “Dan’s Birthday” turned into “Dan-s Birthday”, so I had to change them back. I’ll take care of that one, since it’s purely a “Me” thing at this point…

    Thanks for checking it out – glad it was useful!


  6. admin says:

    “Would love to see someday, if we can automate the script to add photos to a preset of collections as they’re uploaded.”

    Could you expand on this a bid? Is this more than just a Cron type action where it periodically runs the script? Is this more like a background task – like a drop folder action in Mac (I think that’s what they’re called)?


  7. Mark says:

    Nice script! Thanks for providing it. Some issues I’ve been addressing as I’m using it.

    a) On Tiger 10.4.x, I discovered I needed to install PHP5 as only PHP4 is pre-installed.
    http://www.entropy.ch/software/macosx/php/ did the trick and included SOAP.
    On Leopard 10.5.x, I discovered while PHP5 is present, I still need to install a SoapClient.

    b) The script makes all titles the file name (stripping out the extension and converting from _ to a space and makes the caption blank. My files had IPTC tags (Title, Caption-Abstract) in them which Zenfolio was able to use. By commenting out:
    # ‘updater’ => array(‘Title’ => $Title, ‘Caption’ => ”
    # ));
    I stopped the override and allowed the JPEG IPTC tags to be used.

    b) You might want to note to the end-user to use the Zenfolio userid, not the email address, to login. I found that using the email address did successfully authenticate, but caused a fault on the LoadGroupHierarchy call.

    c) I wanted the script to skip all directories with a certain name, regardless of path, not just directories from “root”/name. For example say in any depth traversal I find an end directory called “tn” which stores thumbnails.
    By changing this snippet (below), the script does a wildcarded “*” search for paths ending with that particular directory. (maybe “*/” would be more precise.
    # if (is_array($skip)) foreach ($skip as $Item) $Skip[] = $path.”/”.$Item;
    if (is_array($skip)) foreach ($skip as $Item) $Skip[] = “*”.$Item;

    d) I have a local text file, “header.txt” that contains the “caption” for each folder, that it is in. While uploading to Zenfolio, I would want Zensync to create each group or gallery with captions pre-populated with the contents. I’m currently working on this feature.

    e) In Zenfolio, I know only Galleries can contain pictures, and Groups can contain any number of galleries. The script creates groups down to the deepest subdirectory, then creates a Gallery titled “Photos” in that group to contain the photos. But this adds a navigational layer to the library – there’s always a single gallery titled Photos (and no caption) in the end, rather than the second last node being a gallery. It seems silly for the majority of groups to only contain one gallery.

    I’m currently working on seeing how I can create galleries for the end-nodes and avoid having a dedicated gallery titled “Photos” inside the named group. I have already noticed that the script intelligently doesn’t create new groups nor new photos if it already finds an existing photo or group created (this mechanism apparently works even after I have removed the filename->title mechanism above).

    I can see some issues if I happen to update the directory structure with new subdirectories (let’s assume photos are always stored at the deepest node, not in intermediate positions). What was previously a gallery may now have to be a group holding two galleries. Have you thought about this issue?

    f) With regard to Prasad’s question about automating the script to add photos to a preset of collections, I think he would like the script to not just upload photos to a gallery, but to also add the photo link to one or more “collections”. I guess those collections can either be the uploader’s own, or possibly another user’s (might need more user-id’s then). A good use of this would be to automatically add photos to a friend’s collection as they are uploaded.


  8. Needs Assistance says:

    Could someone who has gotten this running on Windows XP please post a step-by-step guide for installation (along with the necessary PHP instructions) and basic usageguide for a non-programmer. I have downloaded PHP and this Tgz file and uncompressed them both. I don’t see the mentioned soap.dll , though the php manual indicates that you need the gnome xml library (?) and that PHP needs to be installed/run? with “soap enabled” in order to use it. I am very confused but this program seems to be the way to upload my pictures without having to do each subfolder of pictures individually. Thanks for any assistance.

  9. admin says:

    Needs Assistance,

    Check out this post, it should get you where you want to go:



  10. Dan,

    Thanks tons for this terrific script. I only just recently discovered Zenfolio and I am now in the process of migrating my self-hosted Gallery2 photos to Zenfolio – all 34GB worth of it.

    During the initial run, which I left unattended for a few hours, I returned to my PC (Ubuntu 8.04) to see lines such as:

    Uploading pict0079.jpg to Zenfolio…
    Error: /usr/local/web/buberel/g2data/albums/events/sf-peace-march/pict0079.jpg Error Code:

    No error code information was printed. Simply restarting the script seemed to solve the problem – uploading resumed – but any ideas what might have caused this error? Might it be due to the large number of files?


  11. Cause of error determined: The cause of the errors in my particular case were images that exceeded the 12MB single-file size limit. Zensync displays:

    Uploading collage_7_1_tiff.jpg to Zenfolio…
    Error: /usr/local/web/buberel/g2data/albums/homegarden/family-archives/album71/collage_7_1_tiff.jpg Error Code:

    But no actual error code. This seems to indicate that in cases of files exceeding the size limit:

    echo “Error: $OrigPath Error Code: “.$xml[6].”\n”;

    the $xml[6] element is null/empty. Is there some other aspect of the reply XML payload that would indicate the file is too large?

  12. One last update-

    After performing a large transfer, I noticed that most of my images had not appeared on Zenfolio.com. After poking around a bit, I discovered that Zensync only uploads JPG files!!! Yikes! Most of my photos are PNG formatted, and were left behind.

    I went ahead and modified dirclass.inc and zenzync.php:

    – Added support for PNG, GIF and TIFF images.
    – Modify skip-list behavior to match glob patterns against file and dir names.

    If you’ve got an email address, I can send you the updated versions.


  13. Spacey Stacey says:


    Thanks for providing such a wonderful script. If I could get it fully functioning without throwing this error

    PHP Warning: feof(): supplied argument is not a valid stream resource in C:\1apicstoweb\zensync\dirclass.inc on line 163
    PHP Warning: fgets(): supplied argument is not a valid stream resource in C:\1apicstoweb\zensync\dirclass.inc on line 164

    after running for a while, I would be beyond thrilled.

    After the script is running for a while, maybe after 30 pictures or so, it throws this error message which just scrolls endlessly. Any help would be gratefully appreciated.


  14. Tim Hoerner says:

    I hope you can help me.
    I have installed Zensync according to your instructions in “Running on XP”.
    When the script runs, I get the following error:
    “PHP Parse error: syntax error, unexpected T_STRING in C:\Zensync\zensync.php on line 12”

    Do I have to change information on the line labeled “$title”?

    How does the program know where to place files in my Zenfolio folders? I didn’t see any place to tell Zensync where to start looking for files.

    Thanks for your help.

    Tim Hoerner///

  15. Daniel says:

    I am trying to run this on OS X 10.5.6. I have PHP5 installed and the config shows Soap active: ‘./configure’ ‘–disable-dependency-tracking’ ‘–prefix=/usr/local/php5’ ‘–with-apxs2=/usr/sbin/apxs’ ‘–with-config-file-scan-dir=/usr/local/php5/php.d’ ‘–with-openssl=/usr’ ‘–with-zlib=/usr’ ‘–with-zlib-dir=/usr’ ‘–with-gd’ ‘–with-ldap’ ‘–with-xmlrpc’ ‘–enable-exif’ ‘–enable-soap’ ‘–enable-sqlite-utf8’ ‘–enable-wddx’ ‘–enable-ftp’ ‘–enable-sockets’ ‘–with-bz2=/usr’ ‘–enable-zip’ ‘–enable-pcntl’ ‘–enable-shmop’ ‘–enable-sysvsem’ ‘–enable-sysvshm’ ‘–enable-sysvmsg’ ‘–enable-memory-limit’ ‘–enable-mbstring’ ‘–enable-bcmath’ ‘–enable-calendar’ ‘–with-iodbc’ ‘–with-mssql=shared,/usr/local/php5’ ‘–with-mhash=shared,/usr/local/php5’ ‘–enable-memcache’ ‘–with-imap=../imap-2007e’ ‘–with-kerberos=/usr’ ‘–with-imap-ssl=/usr’ ‘–with-libxml-dir=shared,/usr/local/php5’ ‘–with-xsl=shared,/usr/local/php5’ ‘–with-gettext=/usr/local/php5’ ‘–with-curl=shared,/usr/local/php5’ ‘–with-png-dir=/usr/local/php5’ ‘–with-jpeg-dir=/usr/local/php5’ ‘–enable-gd-native-ttf’ ‘–with-freetype-dir=/usr/local/php5’ ‘–with-mysql=shared,/usr/local/php5’ ‘–with-mysqli=shared,/usr/local/php5/bin/mysql_config’ ‘–with-pdo-mysql=shared,/usr/local/php5’ ‘–with-pgsql=shared,/usr/local/php5’ ‘–with-pdo-pgsql=shared,/usr/local/php5’ ‘–with-mcrypt=shared,/usr/local/php5’


    Soap Client enabled
    Soap Server enabled

    Directive Local Value Master Value
    soap.wsdl_cache 1 1
    soap.wsdl_cache_dir /tmp /tmp
    soap.wsdl_cache_enabled 1 1
    soap.wsdl_cache_limit 5 5
    soap.wsdl_cache_ttl 86400 86400

    However, I am still getting the error message: Fatal error: Class ‘SoapClient’ not found in /Users/dcoughli/Sites/zensync/zensync.php on line 25

    I know enough to be dangerous, but not much more. Any help would be appreciated! Thanks


  16. admin says:

    Hmm.. not sure what’s going on there, Daniel. I tested it on a stock OS X machine, so maybe it’s with your custom compile of PHP? I just updated my machine to 10.5.7, so I’ll give it a whirl.


  17. Pingback: New ZenSync2 released! – harim fotografien

  18. Daniel says:


    Love the idea of the script, but I’m stuck on figuring it out. I’ve downloaded the file and have unpacked it and edited the file. Now, I’m just not sure how to execute it. I’m running Mac OS 10.4 w/ PHP 5 installed.

    Thanks for the help.

  19. admin says:

    Sorry for the late reply – but I don’t know what to say about getting it to work in 10.4 – any way you can upgrade to Leopard? Tiger just had so many… quirks. Take a look at Hirim’s version (Zensync 2):



  20. marc says:

    hi dan.

    was just testing out ZenSync. i ran into a bug (fatal error, no less) and wanted to get your feedback.

    Fatal error: Uncaught SoapFault exception: [HTTP] Error Fetching http headers in /Users/marc/Downloads/zensync/dirobj.class.php:412
    Stack trace:
    #0 [internal function]: SoapClient->__doRequest(‘__call(‘LoadPhoto’, Array)
    #2 /Users/marc/Downloads/zensync/dirobj.class.php(412): SoapClient->LoadPhoto(Array)
    #3 /Users/marc/Downloads/zensync/dirobj.class.php(134): DirObj->UpdatePhoto(Object(SoapClient), ‘513287174’, Object(DirectoryIterator))
    #4 /Users/marc/Downloads/zensync/dirobj.class.php(76): DirObj->ScanDir(Object(SoapClient), ‘vtUT2knX4UgZMAg…’, Object(stdClass), NULL, Array, ‘rudolph_session’)
    #5 /Users/marc/Downloads/zensync/dirobj.class.php(44): DirObj->ScanDir(Object(SoapClient), ‘vtUT2knX4UgZMAg…’, Object(stdClass), NULL, Array, ‘teuscher’)
    #6 /Users/marc/Downloads/zensync/zensync.php(108): DirObj->Load(Object(SoapClient), ‘vtUT2knX4UgZMAg…’, 592241835, Object(stdClass), NULL, Array, ‘/Users/marc/Des…’, in /Users/marc/Downloads/zensync/dirobj.class.php on line 412

    I was changing the access controls to my galleries on the Zenfolio site as the photos were uploading, not sure if that might have been the cause?

  21. admin says:

    I haven’t done an upload in a while (have several months of photos queued at this point), but just did a test run, and it ran fine for me. I run Zensync on a webhost running Linux (Debian, I think, not sure). I’ve run it on a Mac previously, so assume things still work.

    Has it worked in the past? I would wager that changing access controls while uploading isn’t in your best interests. Try a fresh upload to an unprotected directory and see what happens – I don’t use directory permissions, so this could also be a conflict there as well.


  22. Miss(ing) Directory says:


    I keep getting this error…

    Getting user’s existing Hierarchy

    Fatal error: Uncaught SoapFault exception: [zf:E_NOSUCHOBJECT] 50018: There is no such folder. in /Volumes/SSPvol1Drobo/zensync2/zensync.php:94
    Stack trace:
    #0 [internal function]: SoapClient->__call(‘LoadGroupHierar…’, Array)
    #1 /Volumes/SSPvol1Drobo/zensync2/zensync.php(94): SoapClient->LoadGroupHierarchy(Array)
    #2 {main}
    thrown in /Volumes/SSPvol1Drobo/zensync2/zensync.php on line 94

    the config file looks like this….

    # Specify your image depot directory
    “localpath” => “/upload to zenfolio/”,
    “title” => “”,

    and yes there really is a folder called “upload to zenfolio” with the images in it in the same folder as zensync.php

    any ideas?


  23. Kenneth Ingham says:

    I am getting a warning and an error.

    PHP Warning: date(): It is not safe to rely on the system’s timezone settings. You are *required* to use the date.timezone setting or the date_default_timezone_set() function. In case you used any of those methods and you are still getting this warning, you most likely misspelled the timezone identifier. We selected ‘America/Denver’ for ‘MST/-7.0/no DST’ instead in /tmp/zensync/zensync.php on line 112

    More of a problem is the error:
    Uploading ElMorro_9152.jpg (2012855 Bytes) to Zenfolio…
    ZF Error: 400 Bad Request: Bad Request (Invalid URL): /tmp/nmlc/ElMorro_9152.jpg

    I get this for every file that it tries to upload. There are no other messages indicating any problems that I see.

    Linux Socrates.site #1 SMP PREEMPT 2010-10-25 08:40:12 +0200 x86_64 x86_64 x86_64 GNU/Linux


  24. admin says:

    That is curious. Are there any special characters with the filename? Has it EVER worked for you? I’m about to do a batch upload of Christmas photos, so I’ll do some testing.

    The timezone error shouldn’t be anything big – it’s just a standard PHP warning, and date/time is only used for timing the upload process.


  25. Courtney says:

    Will this work on Windows 7? I am trying to get this set up… I need instructions much like the ones that were available for XP 🙁 Can someone help? I am excited to try this as I am new to Zenfolio.

    Thank You

  26. I experienced the same error as Kenneth above while setting up a new Zenfolio with Zensync instance for a friend (the third for me…):

    ZF Error: 400 Bad Request: Bad Request (Invalid URL): /(location of image).jpg

    It was occurring because I hadn’t created a gallery on Zenfolio yet and didn’t have the test image in a subdirectory; once I put the test image in a subdirectory inside the image depot directory, the upload completed successfully.

    Thanks for making Zensync available. It’s great!

  27. Robin Priest says:

    I live in a 2 mile radius in rural Maine that does not have access to high speed internet. Since I have to use a satellite dish I have limited bandwidth and a slow connection. This causes many problems in that I am unable to upload from my home and it takes several hours to upload to my Zenfolio site. I user this site for my sports photography and have lost orders because I could not get the pics up fast enough -will Zensync work for me so I can upload from home without using all my bandwidth?

  28. admin says:

    Zensync will most likely use all your available upload bandwidth. There are no throttling controls built in, and I haven’t considered what it would take to do so.

    Depending on your OS, there are 3rd party controls or Router tweaks that you could do that would be useful for this, but I have no experience using them.

    From my experience, I queue up a bunch of updates, and run the sync late at night before I go to bed. It has worked for me for quite a long while now.

    Good luck & let me know how it works out for you!


  29. Lee Waxman says:

    I also have an old web site I created using iweb. This site is going away on June 30, 2012. Do you have the ability to take these images and transfer them to Zenfolio?
    Thank you.
    Lee W

  30. Alberto says:

    Hi, i would like to move to your service and want to move my photos from http://www.viewbook Can you help me to do this ? I wish to buy the Premium Pro.

  31. Jenkins says:


    I encounter the following when I try to run the script. IT happened only after uploading 2000 plus photos, fwiw.

    Response from ZF server:
    [5]: Set-Cookie:
    zf_5y_visitor=Xs07nAStkozEQFjtNoXJpsqcCfYAAAAA8s9paWSHRPn9; e [9]:
    Content-Type: text/plain; charset=utf-8
    File: IMG_2131.JPG
    UploadURL: http://up.zenfolio.com/fotokraft/p657547703/upload.ushx
    DirPath: /home/zensync/photos/Families/IMG_2131.JPG
    Uploading IMG_2131.JPG (6322315 Bytes) to Zenfolio…
    ZF Error: 403 Forbidden: :

  32. admin says:

    Sorry, no, ZenSync is for taking local photos (local anywhere – on a server is considered local if ZenSync is running on the server) and putting them on Zenfolio.

  33. admin says:

    Not a problem. Command-line tools aren’t always the easiest to configure or get running. Fortunately, once it is, ZenSync has been quite reliable for me!

  34. admin says:

    Sorry, I don’t think so. You will need to download your photos to your local computer (or server) and run ZenSync on there. I don’t support any service -> Zenfolio transfers with ZenSync.

  35. admin says:

    It looks like an Error from Zenfolio, nothing I can do about that. The good thing is that ZenSync won’t try and re-upload those 2000 photos – just re-run the script and it will resume from where it left off. I could add extra retry code in there in the future, but in this case you might have run into a storage limit, or some other arbitrary throttle where that won’t help.

  36. Lee Shelly says:

    I have having a recurring issue that I haven’t encountered before. After successfully uploading several images, the terminal will stop…not frozen…I can close the window etc, but the upload just stops. It has only been an issue since the summer of 2013.

    I’m running on Mac OSX 10.8.5 and it’s the same computer I have been using for zensync uploads for the past 3 years.

    Has something changed?

  37. admin says:

    Nothing has changed as far as I can tell. I just ran an upload to my personal site, and it ran fine. It’s running from Linux, however, not OS X. If PHP changed on OS X with a recent update, there could be something that messed up there.

  38. John Bailon says:

    Hi Dan, any chance you would upload Zensync to Github so people might be able to contribute to it? I’d be willing to fix a few bugs if I can.

  39. admin says:

    Sure can do, but the download IS source (php) so feel free to edit what you want.

  40. CRyder says:

    I am receiving the same error that two people mentioned previously. Zensync works but when it tries to upload it fails with the following error:

    Uploading DSC_0110c.JPG (1156236 Bytes) to Zenfolio…
    ZF Error: 400 Bad Request: : /Users/booth/Desktop/PhotosOut/DSC_0110c.JPG

    I cannot figure out what I’m supposed to do to get it to work. The code is not commented and there is nothing to indicate what the issue is specifically. Can you give me an idea as to how I can determine what it’s looking for?

  41. CRyder says:

    Regarding my last message – I figured out the problem I was having. Since it seems like other people have had the problem and I was not understanding their explanation (my fault) I will share my revelation for those who need it:

    I was thinking of the local folder (in my case, called “PhotosOut”) as the place to put photos I wanted on Zenfolio. I was putting photos directly in that folder, and when running ZenSync2, I was getting a “bad request” error.

    I was thinking about it wrong. Here’s how it works…The folder on your computer (PhotosOut) is the equivalent of “all photographs” which is the parent directory on your Zenfolio account. When you put photos directly into your folder locally, Zensync thinks you want them in the parent directory, which zenfolio will not allow you to do. Thus the error.

    Instead, you have to create subfolders within your local home directory. Now when zensync tries to upload, it either puts them in the corresponding gallery on zenfolio, or creates one if none existed before. Main folder = All Photographs; sub folders = galleries.

    This may seem obvious to some, but it had me pulling my hair out for a while. Now that I understand and created a subfolder, it works like a charm! I hope this explanation helps someone else. Of course, if I am still wrong and have just get it working through dumb luck, someone please correct me.

Leave a Reply

Your email address will not be published. Required fields are marked *