Select to view content in your preferred language

Synchronous Custom Printing - output names are not unique?

2308
17
Jump to solution
06-20-2013 11:38 AM
TracySchloss
Honored Contributor
I have a custom print service set up, defined as synchronous.  I'm using the print widget and at first I thought I had everything working.  As I'm testing, I started to notice that some of my printouts weren't what I currently had on the screen, they were ones that I had created a little earlier.

I started looking closer at the output created in my arcgisoutput\printTemplate\ExportWebMap_GPServer, studying how long those files were around before they were automatically cleared out.  I haven't got it down to the minute, but around 15 minutes seems to be their life cycle.  Next I realized the once these were cleared, new files getting generated have the exact same names as the ones that I created several minutes ago!  Because the names are the re-used, the browser is displaying the cached PDF from the earlier print request, not the one I just created.


How can I work around this?  Why aren't these names unique?  Is this the behavior of the out of the box printTools or specific to my custom service?  Do I Just tell the users they have to clear their browser histories if they start seeing this?

I originally had this set up as asynchronous, but that came with its own set of problems, probably because the code sample I'm using was based on synchronous print requests.  I am 3 weeks into trying to get this print to work and I'm running out of time!
0 Kudos
17 Replies
JohnGravois
Deactivated User
printTask includes the method execute(), so you'll definitely be fine working with your synchronous print service

heres a little more information from my bug report that should help clarify why the problem only occurs "sometimes".

Custom Print Services generates the same 32-character string for all its output files, which causes old print requests to be displayed again.

Steps to reproduce:
1.  Submit several print requests to the OOTB 10.1 print service and notice that each output filename includes a random 32-character sequence.
2.  Publish a Custom Print Service (using existing templates) and notice that the same 32-character string is repeated in all output files. Only incremented numbers appended to the end guarantee the filename is unique (see attached screenshots).

This causes a problem in web applications when an additional print request is submitted after previous jobs have already been deleted from the server. Because the response URL can easily be identical, stale content from the cache might be displayed instead of the correct printout.

Sample application attached (can also be found at http://[internalserver]/printTask.html).
1.  Open the application and click print
2.  Pan the map to a different location
3.  Wait 15 minutes and send another print request
Notice that if the URL is identical, the first printout will be displayed again. It is necessary to force a refresh of the page to display the appropriate output.
0 Kudos
MattLane
Frequent Contributor
i just wanted to chime in and let you all know that this is a REST bug that I logged a little while back which has been tested and confirmed fixed in 10.2.

[NIM090204:When using a custom print service, sometimes old print requests are returned due to the way output files are named]

sorry for the inconvenience.


Tested and fixed in 10.2, but can we get a patch or at least roll it into the next service pack, for 10.1?

The cache-busting they mention above isn't always the best idea either. If the user runs the print, then waits 15 minutes (coffee break?) before hitting the link, they will be getting someone else's print.
0 Kudos
TracySchloss
Honored Contributor
I didn't find a basic printTask example, so I put this together for whoever might be reading the forums about printing issues. This looks a lot like the print dijit, but is based on printTask and printParameters.  It still doesn't the address the issue of 'duplicate' PDF output.  But it does seem less buggy than the print dijit and it's working for me in IE.

I don't see where I can control the output name.  I wonder if there are maybe additional options if I had authored my service with Python instead of the Export Web Map server tool?

This is based on my custom print service, but it's generic enough I'd think it would work with the OOTB printTool with minimal changes.

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"> 
<html> 
  <head> 
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> 
    <meta http-equiv="X-UA-Compatible" content="IE=7, IE=9, IE=10" /> 
    <!--The viewport meta tag is used to improve the presentation and behavior of the samples  
      on iOS devices--> 
    <meta name="viewport" content="initial-scale=1, maximum-scale=1,user-scalable=no"/> 
    <title>Print Task Example</title> 
    <link rel="stylesheet" type="text/css" href="https://serverapi.arcgisonline.com/jsapi/arcgis/3.4/js/dojo/dijit/themes/claro/claro.css"> 
    <link rel="stylesheet" type="text/css" href="https://serverapi.arcgisonline.com/jsapi/arcgis/3.4/js/esri/dijit/css/Popup.css"> 
    <link rel="stylesheet" type="text/css" href="https://serverapi.arcgisonline.com/jsapi/arcgis/3.4/js/dojo/dojox/layout/resources/FloatingPane.css">
    <link rel="stylesheet" type="text/css" href="https://serverapi.arcgisonline.com/jsapi/arcgis/3.4/js/dojo/dojox/layout/resources/ResizeHandle.css">
    <link rel="stylesheet" type="text/css" href="https://serverapi.arcgisonline.com/jsapi/arcgis/3.4/js/esri/css/esri.css" >    
    <link type="text/css" rel="stylesheet" href="css/style.css">
    
    <script type="text/javascript">var dojoConfig = {parseOnLoad: true};</script> 
    <script type="text/javascript" src="https://serverapi.arcgisonline.com/jsapi/arcgis/?v=3.4"></script> 
    
    <script type="text/javascript"> 
      dojo.require("dijit.layout.BorderContainer"); 
      dojo.require("dijit.layout.ContentPane"); 
      dojo.require("dojox.layout.FloatingPane");
     dojo.require("dijit.form.Button");
    dojo.require("dijit.form.Select");
      dojo.require("esri.map"); 
      dojo.require("esri.dijit.Popup"); 
      dojo.require("esri.layers.FeatureLayer");
      dojo.require("dijit.form.Button");
      dojo.require("esri.tasks.PrintTask");
       
      var loading;
      var map; 
      var spatialReference;    
      var idFromClick = true;
      var districtLayer;
      var geometryPt;
      var currentExtent;
      var layouts = [];
      var templates = [];
      var template;
      var printServiceUrl = "https://myPrintServerName/arcgis/rest/services/printTemplate/ExportWebMap/GPServer/Export%20Web%20Map";
       
    function init() {     
      spatialReference = new esri.SpatialReference({wkid: 102100 });
        startExtent = new esri.geometry.Extent(-10583000, 4287025, -9979000, 4980462, spatialReference);
        map = new esri.Map("map",{   extent:startExtent  });
        var basemap = new esri.layers.ArcGISTiledMapServiceLayer("https://server.arcgisonline.com/ArcGIS/rest/services/Canvas/World_Light_Gray_Base/MapServer"); 
        map.addLayer(basemap); 
   
        roadLayer = new esri.layers.ArcGISDynamicMapServiceLayer("https://services.arcgisonline.com/ArcGIS/rest/services/Reference/World_Transportation/MapServer",{id:'countyLayer'});
        map.addLayer(roadLayer);   
        
        dojo.connect(dijit.byId('map'), 'resize', map, map.resize);//resize the map when the browser resizes      
 
 setUpPrinting();
    }//end init function

 
function clearTextInput (id) {
    dojo.byId(id).value="";
}
//functions for printing
function openPrint () {
  clearTextInput('txtTitle');
  var fp = dijit.byId('floater_print');
   if ((fp.style = "visibility: hidden;") || (fp.style = "VISIBILITY:hidden;")) {
      fp.style.visibility="visible";
      fp.show();
   }      
}
function setUpPrinting() {
    var templateList = dijit.byId("templateSelect");
     layouts = [{
            "layoutName": "Custom_Landscape",
            "label": "Landscape",
            "format": "PDF",
            "options": {
                "legendLayers": [], // empty array means no legend
                "scalebarUnit": "Miles",
                "titleText": ""
            }
        }, {
            "layoutName": "Custom_Portrait",
            "label": "Portrait",
            "format": "PDF",
            "options": {
                "legendLayers": [], // empty array means no legend
                "scalebarUnit": "Miles",
                "titleText": ""
            }
        }];
       dojo.forEach(layouts, function(layout){
            var pTemplate = new esri.tasks.PrintTemplate();
            pTemplate.layout = layout.layoutName;
            pTemplate.label = layout.label;
            pTemplate.format = layout.format;
            pTemplate.layoutOptions = layout.options;
            pTemplate.showAttribution = false;
            templates.push(pTemplate);
                       
            templateList.addOption({
             label: layout.label,
             value: layout.label
           });
            
        });
        
}


function submitPrint() {
    var deferred;
    var printTitle = dojo.byId("txtTitle").value;
    var printParams = new esri.tasks.PrintParameters();
    printParams.map = map;
    var status = dojo.byId("printStatus");
    status.innerHTML = "Printing ...";
    var e = dijit.byId("templateSelect");
    var choice = e.value;
    if (choice == "Portrait") {
        template = templates[1];
    }else{
        template = templates[0];
    }
    if (!template) {
        template = templates[0];
    }
    printParams.template = template;
    template.layoutOptions.titleText = printTitle;
    
    var printTask = new esri.tasks.PrintTask(printServiceUrl,printParams);
    //printTask.execute(printParams,printComplete,printError);
    deferred = printTask.execute(printParams);
        deferred.addCallback(function (response){
         //   console.log("response = " + response.url);       
        status.innerHTML = "";

   var select = dijit.byId("templateSelect");
   var selectOptions = select.getOptions();
  select.set("value", "Choose Print Format");
   
            var link = dojo.byId("printLink");
            link.innerHTML = "<a  href="+response.url+ " target=_blank ;'>Printout</a> ";
            link.onclick = function(){link.innerHTML = '';};
        });
    
    deferred.addErrback(function (error) {
        console.log("Print Task Error = " + error);
        status.innerHTML = "Print Error" + error;
    });
    
}

function printError(err) {
    console.log("Printer Error: " + err);
    
}
      dojo.addOnLoad(init); 
    </script> 

 </head> 
  <body class="claro">
      <div dojotype="dijit.layout.BorderContainer" data-dojo-props="design:'headline'"  style="width: 100%; height: 100%; margin: 0; border:0px;"> 
      <div id="header" dojotype="dijit.layout.ContentPane" region="top">  Print Task Example </div>
       <div dojotype="dijit.layout.ContentPane" id="centerPane" region="center"> 
                    <button id="btnPrint" dojotype="dijit.form.Button" onClick="openPrint();">Print</button> 
            <div id="map" dojotype="dijit.layout.ContentPane" title="Map" >
             <div dojoType="dojox.layout.Dock" id="dock_print"></div>
            </div>
        <div id="floater_print" dojoType="dojox.layout.FloatingPane"  title="Print Tools" dockTo="dock_print" style="visibility:hidden" closable="false" resizable="true"  dockable="true" >     
          
            <div id="note">
              <ol>   
              <li> Enter a Title    
              <input id="txtTitle" style="width:250px" type="text"  value="Enter a map title" class="textBox"
              onclick="clearTextInput('txtTitle');"  />     
              </li>   
                <li> Click the dropdown arrow on the Print format to choose Landscape or Portrait. </li>
                <li> The 'Printing' prompt indicates your page is being generated. </li>
                <li> When the printout is ready, click Printout to view your PDF.</li> 
             </ol>
        
    <select  id="templateSelect" data-dojo-type="dijit.form.Select"  >
         <option>Choose Print Format</option>
     </select>
<button id="btnPrintSubmit" dojotype="dijit.form.Button" onClick="submitPrint();">Print</button> 
        </div>
<div id="printStatus"></div>
<div id="printLink"></div>
    </div>
   </div>  
  </body>
</html> 
0 Kudos
JianHuang
Deactivated User
This is a service side bug. Luckily we have a workaround on client.
If you are using printTask, just simply attach a time stamp at the end of the result url. If you are using printDijit, please try the code
dojo.connect(printer, "onPrintComplete", function(result){
  var currentTime = new Date();
  result.url += "?ts="+currentTime.getTime();
});
TracySchloss
Honored Contributor
Could you clarify where this goes since I'm using printTask and not the dijit?  I'm appending the timestamp to the end of the response.url before I provide that as a link to the user and that's enough to never see old PDFs?

    deferred = printTask.execute(printParams);
        deferred.addCallback(function (response){ 
             var time = new Date();
    var outputUrl = response.url + '?time=' + time;  
            var link = dojo.byId("printLink");
             link.innerHTML = "<a  href="+outputUrl+ " target=_blank ;'>Printout</a> ";
         //   link.innerHTML = "<a  href="+response.url+ " target=_blank ;'>Printout</a> ";
        });
0 Kudos
TracySchloss
Honored Contributor
Either I'm not using the right syntax or this isn't a solution.  After several minutes of creating and monitoring my PDF output, I'm still see previously cached PDFs.  Bummer.
0 Kudos
JianHuang
Deactivated User
try time.getTime(), which returns the unix time.
0 Kudos
TracySchloss
Honored Contributor
Time worked instead of date.  When I looked at the ?time parameter when it was Date, it was truncating on the day ?time=Mon.  That's no good.  Switching it to the time instead took care of it.  I could watch the original big long guid name get removed and replaced and see the browser properly show the newer version by the same name.

Here's the updated submitPrint function:
function submitPrint() {
    var deferred;
    var printTitle = dojo.byId("txtTitle").value;
    var printParams = new esri.tasks.PrintParameters();
    printParams.map = map;
    var status = dojo.byId("printStatus");
    status.innerHTML = "Printing ...";
    var e = dijit.byId("templateSelect");
    var choice = e.value;
    if (choice == "Portrait") {
        template = templates[1];
    }else{
        template = templates[0];
    }
    if (!template) {
        template = templates[0];
    }
    printParams.template = template;
    template.layoutOptions.titleText = printTitle;
    
    var printTask = new esri.tasks.PrintTask(printServiceUrl,printParams);
    deferred = printTask.execute(printParams);
        deferred.addCallback(function (response){  
             var d = new Date();
            var dateTime =  d.getTime(); 
            var outputUrl = response.url + '?time=' + dateTime;  
        status.innerHTML = "";

   var select = dijit.byId("templateSelect");
   var selectOptions = select.getOptions();
  select.set("value", "Choose Print Format");
   
            var link = dojo.byId("printLink");
             link.innerHTML = "<a  href="+outputUrl+ " target=_blank ;'>Printout</a> ";
         //   link.innerHTML = "<a  href="+response.url+ " target=_blank ;'>Printout</a> ";
            link.onclick = function(){link.innerHTML = '';};
        });
    
    deferred.addErrback(function (error) {
        console.log("Print Task Error = " + error);
        status.innerHTML = "Print Error" + error;
    });
    
}
0 Kudos