Question
Timothy Leavitt · Aug 31, 2022

Weird file encoding issue with %CSP.BinaryStream / CSP file upload

Consider the simplest possible CSP file upload/download page - you upload a file, it's saved in the database, and the file is immediately re-download via %CSP.StreamServer:

Class DC.Demo.CSPUpload.Page Extends (%Persistent, %CSP.Page)
{

Property stream As %CSP.BinaryStream [ Required ];

ClassMethod OnPage() As %Status
{
	&html<<form method="post" enctype="multipart/form-data">
		<input type="file" name="file" />
		<input type="submit" />
	</form>>
	quit $$$OK
}

ClassMethod OnPreHTTP() As %Boolean [ ServerOnly = 1 ]
{
	#dim %request As %CSP.Request
	#dim %response As %CSP.Response
	if %request.Method = "POST" && %request.GetMimeData("file") {
		set inst = ..%New()
		set inst.stream = %request.GetMimeData("file")
		$$$ThrowOnError(inst.%Save())
		do inst.stream.SetAttribute("ContentDisposition","attachment; filename="""_inst.stream.GetAttribute("FileName")_"""")
		set %response.Redirect = "%25CSP.StreamServer.cls?STREAMOID="_..Encrypt(inst.stream.GetStreamId())
	}
	quit 1
}

Storage Default
{
<Data name="PageDefaultData">
<Value name="1">
<Value>%%CLASSNAME</Value>
</Value>
<Value name="2">
<Value>stream</Value>
</Value>
</Data>
<DataLocation>^DC.Demo.CSPUpload.PageD</DataLocation>
<DefaultData>PageDefaultData</DefaultData>
<IdLocation>^DC.Demo.CSPUpload.PageD</IdLocation>
<IndexLocation>^DC.Demo.CSPUpload.PageI</IndexLocation>
<StreamLocation>^DC.Demo.CSPUpload.PageS</StreamLocation>
<Type>%Storage.Persistent</Type>
}

}

This works fine for most file types, but for HTML files (at least - maybe other types too), it doesn't work - both on IRIS 2021.2 and on an earlier version I'm running too. The resulting downloaded file has a BOM at the beginning and a NUL every other character.

Has anybody else fought with this before?

Product version: IRIS 2021.2
$ZV: IRIS for Windows (x86-64) 2021.2 (Build 651U) Mon Jan 31 2022 17:39:04 EST
0
1 73
Discussion (2)1
Log in or sign up to continue

... ended up answering my own question in less time than it took to write it up. Solution (which might just be a workaround) is to force the content-type on the response to be application/octet-stream:

do inst.stream.SetAttribute("ContentDisposition","attachment; filename="""_inst.stream.GetAttribute("FileName")_"""")
do inst.stream.SetAttribute("ContentType","application/octet-stream")
set %response.Redirect = "%25CSP.StreamServer.cls?STREAMOID="_..Encrypt(inst.stream.GetStreamId())

I'd check/set:

set ^%SYS("CSP","DefaultFileCharset")="utf-8"