ASP: Hiding file locations by binary stream reading
I do a lot of work with internet content business – companies that earn their living by managing documents and content, either for their own services or on behalf of customers.
Often this involves making documents on the server available for viewing, but without propagating the URL of the actual file, and with permission checks to ensure that the person viewing the file is authorised to do so.
Here’s a simple technique to make a file, such as a PDF, available without revealing the file’s URL and with a security check.
The trick is to binary read the file to the user’s browser, instead of the user opening the file directly. In ASP we do this with the ADODB.Stream object. This allows us to open the file on the web server as a binary stream and send it to the browser. The user will be none the wiser to the file’s location.
' Run a security check ' Add code here to ensure that the logged in user has permission to view the file ' if we have a file identifier if fileId>0 then ' grab the file's name and location - probably from a database table sqlStr="SELECT filePath,fileName FROM tblMyFiles WHERE fileId="&request("fileId") set rs=Server.CreateObject("adodb.Recordset") rs.cursorlocation=aduseclient rs.cachesize=1 rs.open sqlStr, conn, adOpenForwardOnly,adLockReadOnly ' if the file entry in our database table is found if not rs.eof then ' open the file system object Set objFSO = Server.CreateObject("Scripting.FileSystemObject") ' check the file we want does actually exist If objFSO.FileExists(filePath&lcase(rs("fileName"))) then ' and if it does exist, then spit out to the browser ' open a binary stream for the file Set strOutStream = Server.CreateObject( "ADODB.Stream" ) strOutStream.Type = 1 'adTypeBinary strOutStream.Mode = 3 'adModeReadWrite strOutStream.Open ' load the file into the stream strOutStream.LoadFromFile (filePath&lcase(rs("fileName"))) Response.Buffer = TRUE ' use the content type appropriate to the file - here we're using a PDF Response.ContentType = "application/pdf" Response.AddHeader "content-disposition", "inline; filename=" & rs("fileName") Response.BinaryWrite (strOutStream.Read) Response.End strOutStream.Close Set strOutStream = Nothing end if set objFSO=nothing end if rs.close Set rs=nothing end if