Efficient web printing can be tricky sometimes, especially when you add any level of complexity to it. A single page webmap, using ESRI’s out-of-the-box printing service is fairly straight forward. But start adding in custom templates, custom symbologies in legends, multiple pages/maps, client-side graphics, higher resolution requirements, etc…and things can start getting complicated and you can quickly watch performance take a nose dive! Recently we assisted a client in developing a very complex javascript-based webmap viewer that had some pretty complex requirements for the printing component. We discovered quite a few important tips and tricks that we wanted to share.
The Requirements
- Users should be able to hit a single “print” button, select up to 6 separate maps to print, and get a multipage PDF back.
- Each of the pages in the multipage PDF represent completely separate webmaps.
- Some of the webmaps had client-side graphics that needed to be in the PDF output.
- The standard 96dpi webmap printing was not acceptable, they needed a higher resolution to get labels to print out clearly from the PDF.
- Legends in each printed page should represent only what’s actually showing up in that area the user chose to print. Custom picture marker symbols were also being used.
The Challenges
We first started with the standard out-of-the-box printing service ESRI includes with ArcGIS for Server. Right away we noticed a few significant problems…low resolution on labels and missing symbologies from the legend being the two big ones. Additionally, of course, was that the printing service only handles a single map/page. We started testing out more custom printing solutions such as the one outlined in ESRI’s Advanced Printing Tutorial that capitalizes on the arcpy ConvertWebMapToMapDocument functionality. This worked great and was very fast (10-15 seconds per print job) and also fixed the missing symbologies in the legend issue since it’s actually using all local layers and sybmologies to export the MXD layout to a PDF. Problem was that it DOES use local datasets, which doesn’t account for those client-side graphics layers we needed to print as well. Eventually we had to go back to the standard printing service which uses the ExportWebMap function as sends the data to be printed across the wire from the client (rather than using local dataset equivalents). However, to resolve the missing symbologies problem, we discovered leaving local layers in the Table of Contents of the custom print template MXDs (& using those in the layout’s legend) fixes the missing custom symobls that weren’t coming over in the web calls correctly. We bumped up the dpi in the exportOptions section of the printing call to get the labels printing more clearly. Then we added a custom geoprocessing service to append the PDFs from all the separate webmap printjobs into one final multipage PDF returned to the user. Finally we had our rather complex printing solution working perfectly….or so we thought!
Performance Problems
While this solution (combining custom print templates (including local TOC layers) with the standard ExportWebMap printing service and an AppendPDFs service to merge it all together) worked well, the initial performance was dismal! In the beginning of implementing this solution, to return a 6 page PDF to the user was taking 16-20 minutes! Not acceptable by any stretch of the imagination. How do we improve performance to an acceptable level?
The first problem we discovered was that the 6 separate printjobs were being fired off synchronously, waiting for each page to be returned before firing out the call for the next one. Standard way to do it, but not what we needed for optimal performance. We had setup the printing service itself to run asynchronously, but it was not being used that way by the client viewer. Once that was fixed in the viewer’s code, performance improved significantly, but was still averaging 5-6 minutes to return a combined PDF. Still not acceptable…
We did a lot of research and debugging on what was going on to improve performance. What we ultimately discovered the culprit to be was the dpi setting in the web printing calls. We’d set the dpi request to 300 in the exportOptions since that’s what had been being used by the client’s GIS department to print from ArcMap, but when we started running the printing service locally and timing the results, the bottleneck became very apparent. Testing various dpi’s for individual printjobs showed the following:
- 96 dpi = ~27 seconds
- 200 dpi = ~33 seconds
- 250 dpi = ~1:39
- 300 dpi = ~2:46
For some reason, there appears to be a break-over point at which the web printing service can’t handle that much data and loses performance rapidly. For us in this case, that point was right around 200dpi. (Your situation may vary since number of layers, complexity, size of area, etc all likely contribute.) The PDFs being printed were no bigger than 11”x14” so 200dpi showed no real visible difference as compared to 300dpi in the outputs. By dropping the exportOptions dpi request down to 200, our 6 page PDFs started returning to the user within 1:30 on average and all tests we ran returned in under 2 minutes. Still not instantaneous, but quite a bit better than the original 20 minutes we started with! So the lesson learned with web printing…dpi matters!
Tips & Tricks Summary
Problem Encountered |
Solution/Work-around |
Need multipage PDF, standard web printing is only single page/map. | Fire off all webmap printjobs separately (asynchronously) and then combine outputs using custom AppendPDFs geoprocessing service. |
Custom picture marker symbols not showing up in legend prints. | Use custom print template MXDs with local versions of map service layers in TOC & legend. |
Labels fuzzy in printed PDFs. | Increase dpi of layers in the exportOptions of the Web_Map_as_JSON string. |
Very slow performance in web printing. | Print all pages simultaneously (asynchronously); lower dpi to 200 to reduce size of data to be processed during printing. |
Recent Comments