Paul Hula · May 22, 2020

CSP - Download file, manipulate and return as attachment

Hi All,

   It must be the groundhog days but I can't solve something that I know I've done before.  I have a legacy CSP page on a version of Cache without JSON and just pure Cache.

  I need a CSP page that takes a .xlsx file, manipulates the file (in COS) and then returns a new manipulated file.

  My CSP Page gets the file fine, the problem is then returning the response with the new file as an attachment.  I don't want to pipe to a new csp page with a different content-type so was sure I can set %response.Headers etc to get the reply stream I want.


So my CSP Page (which contains a lot of CSP tags)

<csp:if condition='$data(%request.MimeData("FileStream",1))'>

blah blah

s sc=##class(something).method(iStream, .oStream)

kill %request.Data ; Wrong!
set %request.Data("STREAMOID",1)= ##class(%CSP.StreamServer).Encrypt(oid) ; Wrong!

So oStream contains the stream of the new attachment, how can I get CSP to serve this up as an attachment?, the above is obviously wrong as I'm resetting the %request.Data but manipulating %response doesn't help me at all.

Anyone remember CSP as I certainly have tried to block it from memory...


1 0 6 203


Hi Henrique,

  Not exactly, the excel isn't the problem, it's when I return the XLS to the browser I need the browser to interprut it as a attachment, the problem is the %response creation.

Hello Paul,

I like to work on this problem. In preparation, I found a zen page in Samples namespace and added a file upload control. I define a CSP page to go to on submit. How do I attach a file to a CSP page? Then you want to manipulate the file when received by CSP page. Does the user see the attached file on the CSP page?  Our team has a CSP page that receives an incoming file and then it is passed along to a business service in HealthConnect production. Where do you want the modified file to go?

.xlsx file, manipulates the file (in COS)

How are you manipulating xlsx in InterSystems ObjectScript?

Hi All,

  Thanks for the replies, I certainly haven't explained the problem very well!, so short summary;

CSP page shows file browser (working) that takes a stream (working) sends the file to a Method (working) and then returns a new file into the same CSP page session (not working)

I appreciate this means the CSP will be "stuck" while the method creates the new file.  I have limited access to change any of this under the hood to send to a directory or use an integration engine or any other alternative.

   For Excel we use activate, as said the Excel and sending the file is not the problem.


%CSP.StreamServer is just a helper to cut short some manual labor.

What you need to do is write the file stream back to the device and change three Content-* headers as follows.

Your CSP page has an OnPreHTTP just like every %CSP.Page extended class. You can use this method to modify the Content-Type, Content-Disposition and Content-Length headers. In your case you'll need to use the <script> tag syntax for creating the method.

The example below assumes you're using a class instead.

NOTE: If you really customize your %CSP.Page or %CSP.REST. You don't even need to use the OnPreHTTP method. But I'll be using it here for educational purposes.

ClassMethod OnPreHTTP() As %Boolean [ ServerOnly = 1 ]
   set file = %request.GetMimeData("FileStream")
   if '$isobject(file) return 0

   do ##class(%CSP.StreamServer).FileClassify("XLS", .contentType, .isBinary, .charset)
   do %response.SetHeader("Content-Type", contentType)
   do %response.SetHeader("Content-Disposition", "attachment; filename=""_file.FileName_""")

  return 1

ClassMethod OnPage() As %Status [ ServerOnly = 1 ]
  set iStream = %request.GetMimeData("FileStream")
  $$$QuitOnError(##class(something).method(iStream, .oStream))

  do %response.SetHeader("Content-Length", oStream.Size)

  do oStream.Rewind()
  do oStream.OutputToDevice()

  return $$$OK