htmldelphidownloadwebbroker

How can I output a file to download without saving it on the server first?


Using Delphi XE3, DataSnap/WebBroker, HTML

I create and load a TStringList which I then save it to a file. I put the file location into the action of my HTML form to force a download. How can I do this without saving the file?

MyList := TStringList.Create;  (leaving out try/finally, etc.)
MyList.Add() ....
MyList.SaveToFile(MyFullFileName); 
MyList.Free;

Returning this HTML to WebModuleDefaultHandler:

<html><head /> 
  <body onload="document.FormOne.submit()"> 
    <form id="FormOne" name="FormOne" method="get" 
            action="MyFullFileName"> 
        <input type="submit" id="btSubmit1" name="btSubmit1"  /> 
    </form>
  </body>
</html>

Is there some way I can send MyList without saving it first?

(Recipients are using standard browsers, not Delphi clients)


Solution

  • Do it as a memory stream...

    MyStream:= TMemoryStream.Create;
    try
      MyList:= TStringList.Create;
      try
        MyList.Add() ...
        MyList.SaveToStream(MyStream);
      finally
        MyList.Free;
      end;
      MyStream.Position:= 0;
      Response.ContentType:= 'text/html';
      Response.ContentStream:= MyStream;
    finally
      MyStream.Free;
    end;
    

    When a request comes into the server from the client, you need to pass the stream MyStream back as the Response ContentStream field. Don't forget to always set streams back to 0 before doing anything with them!

    Or, alternatively, you could also do it using the String List's Text property. Like so...

      MyList:= TStringList.Create;
      try
        MyList.Add('<html>');
        MyList.Add('<heading/>');
        MyList.Add('<body>DataSnap Server</body>');
        MyList.Add('</html>');
        Response.ContentType:= 'text/plain';
        Response.Content:= MyList.Text;
      finally
        MyList.Free;
      end;
    

    Typically using streams is best when you need to load/save/host raw files, such as images. It can be very convenient to draw to a canvas, convert that canvas to a JPG image, and save it as a Stream instead of a File. Then, pass it as Response.ContentStream. Therefore, I've gotten more used to using streams because it's a more standard way of returning content.

    PS - If you'd like this file to be able to show as plain text, then use ContentType of text/plain, or if you'd like any type of file to be downloaded as a file like test.txt then you can use application/octet-stream for ContentType.