09-20-2012 10:32 AM
ansient packageI see lots of discussions on packages like what they are, the different types etc., but not much on how to create them.
Here's the situation. I have a stored process that gets sent a csv file to run statistics on.
It needs to produce two results back to the client. One is a pdf with charts and the other is an Excel file.
Right now I have the stored process send the pdf file after the end of the process. The process leaves a dataset on a permanent library on the server.
After the client closes the pdf they can then run another stored process to download the Excel file.
The problem is some other user could get the Excel file(no security problem, just wrong data) so I was asked to delete the file after it was downloaded.
What I need is a transient package to deliver back the pdf and the Excel file so there is never a permanent dataset on the server.
Like I said I have read a lot on packages but just can't seem to get started in the right direction.
Any advice :smileyinfo: would be appreciated?
09-21-2012 04:59 PM
I played with this a bit, but wasn't successful. : )
I was thinking to just write the PDF and Excel file to work directory, then stream them back to the user. I was playing with something like:
ods tagsets.excelxp file="%sysfunc(pathname(work))/myExcel.xls"; proc print data=sashelp.class; run; ods tagsets.excelxp close; ods pdf file="%sysfunc(pathname(work))/MyPDF.pdf"; proc print data=sashelp.shoes; run; ods pdf close; data _null_; file _webout (no_bottom_matter); infile "%sysfunc(pathname(work))/myExcel.xls"; if _n_ = 1 then do; rc = stpsrv_header('Content-type','application/vnd.ms-excel'); rc = stpsrv_header('Content-disposition',"attachment; filename=MyExcel.xls"); end; input ; put _infile_; run; data _null_; file _webout (no_top_matter) recfm=s; infile "%sysfunc(pathname(work))/MyPDF.pdf" recfm=n; if _n_ = 1 then do; rc = stpsrv_header('Content-type','application/pdf'); rc = stpsrv_header('Content-disposition',"attachment; filename=MyPDF.pdf"); end; input c $char1.; put c $char1. @@; run;
But that doesn't work, I suspect for a number of reasons. Basically trying to send two posts (?) back to the browser. And not allowed 2 different headers. Even when I tried just 2 pdf files, couldn't get it working. Looks like no_bottom_matter can't be used with file _webout ???
Anyway, despite my lack of success, I think if you are willing to keep the approach of having 2 different stored processes, something like above might work, if you use sessions. So the first stored process writes the 2 reports to work dir, and streams back the Excel file. The second stored proecss connects to the same session as the first stored process (so can see the 2 reports in the work dir), and streams the pdf file back to the user. It's just a thought, I haven't played with sessions yet.
Hopefully something in this will help, or perhaps encourage someone else to jump in.
09-24-2012 08:08 AM
That is very helpful. Right now the Stored Process I have is run through some http code and the reponse is saved as a pdf and then it is opened in a web browser.
The code is jscript and the client app has it's own http objects, but is very similar to c#:
var response : HttpResponse = HttpClient.GetResponse(HttpRequest);
*The code below opens the file in a Web Browser;
var finsished = form.ShowModalDialog("WebBrowser");
*The open code for the form opens the pdf returned by the SP;
So, I see the example sends back a package that is an excelxp tagset.
How would I return it to a pdf that opens in a web browser and prompts you to save the Excel file?
09-24-2012 12:45 PM
The Tech Support example sends back several different outputs: an HTML file, an RTF file, a CSV file and a SAS dataset all in one zip file or package. I don't know JScript and I don't know what you mean when you say that the "Stored Process is run through some http code and the reponse is saved as a pdf and then it is opened in a web browser." Do you mean that you are using the Stored Process Web Application to invoke the SP? Or do you mean that you have your own front-end code that has embedded JScript in the app that calls the stored process.
When you make a package, you are making the equivalent of a single ZIP file that contains multiple different files inside of it. I thought you wanted a package - -which is what the Tech Support note shows you how to do. A ZIP file can contain a PDF, but to get the PDF out of the ZIP file, the ZIP file has to be opened or unpacked.
I'm also confused because you said that "the example sends back a package that is an excelxp tagset" -- however, the Tech Support example only uses ODS HTML, ODS CSV and ODS RTF. The ODS HTML destination is used to create HTML files 2 different ways -- 1 time with an extension of HTML and another time with an extension of .XLS -- but the example that I posted does not show the use of TAGSETS.EXCELXP. If you wanted your package to contain TAGSETS.EXCELXP output, then you would replace either the ODS HTML or the ODS CSV step with a call to TAGSETS.EXCELXP. But, now, I'm not sure that you really want a package.
For more help with what you want to do, I'd suggest working with Tech Support.
09-25-2012 03:14 PM
After looking at the sample further, I think I see what it's doing.
All the oputs are put into the &_STPWORK directory and then put in a package.
How do you get the package back to the client?
I ran this sample using url:http://sasserver:8080/SASStoredProcess/do?_action=newwindow&_program=%2FShared+Data%2FMyfolder%2FDem...
but it always returns an error tha says:
ERROR: An exception has been encountered.
Please conta technical support and provide them with the following traceback infomation:
The SAS task name is [STP_LP]
ERROR: Read Access Violation STPX_LP
Exception occured at (03B919BA)
Address Frame (DBGHELP API Version 4.0 rev 5)
When I run it in EG it shows the results as 5 differnt types as input, but not the package.
09-26-2012 10:18 AM
When I changed the sp execution options to only run on the workspace server it will return the package to the web browser.
I think this may be the way to go. all you have to do is click the items on the left and they open in their respective program
Does anybody know if there's a way to get rid of that header and replace it with your won?