I've a DataSnap server method
function TServerMethods.GetFile(filename): TStream
returning a file. In my test case the file is a simple .PDF.
I'm sure this function works fine, as I'm able to open files on ObjectiveC client side app's where I've used my own http call to the DataSnap method (no Delphi proxy). The stream is read from ASIHttpRequest object and saved as local file, then loaded and regulary shown in standard pdf reader. I do not kown how exactly ASIHttpRequest manages the returned data.
But on JavaScript client side where I use standard
stream = ServerMethods().GetFile('test.pdf')
JavaScript function, as provided from DataSnap proxy itself, I do not figure out how to show the .pdf data to the user.
Using
window.open().document.write(stream);
a new browser window opens with textual raw data ( %PDF-1.5 %âãÏÓ 1 0 obj << /Type /Catalog /Pages 2 0 R …..)
With
window.open("data:application/pdf;base64," +stream);
I get an empty new browser page.
With
window.open("data:application/pdf," +stream);
or
document.location = 'data:application/pdf,'+encodeURIComponent(serverMethods().GetFile('test'));
I get an new browser page with pdf empry reader and alert “This PDF document could not be displayed correctly”
Nothing changes adding:
GetInvocationMetadata().ResponseContentType := 'application/pdf';
into the DataSnap function.
I've no other ideas...
EDIT
The task is for a general file download, not only PDF. PDF is a test only. GetFile
have to manage .pdf, .xlsx, .docx, .png, .eml, etc...
Your server side code works as expected once you set the ResponseContentType. You can test this by calling the method directly from a browser. Change the class name to match the one you're using:
http://localhost:8080/datasnap/rest/TServerMethods1/GetFile/test.pdf
I'm sure there's a way to display the stream properly on the browser side, but I'm not sure what that is. Unless you're doing something special with the stream, I'd recommend getting the document directly or using a web action and getting out of the browser's way. Basically what mjn suggested.
I can think of a couple of solutions.
1) A quick way would be to allow access to the documents directly.
In the WebFileDispatcher, add a WebFileExtension. Select .pdf and it will fill in the mime type for you. Assuming your pdf documents are in the "docs" folder, the url might look like this:
http://localhost:8080/docs/test.pdf
2) I would probably add an action on the web module. It's a little more involved, but it also gives me more control.
Using this url:
http://localhost:8080/getfile?filename=test.pdf
And code like this in the web action handler (no checking or error handling). The Content-Disposition header suggests a file name for the downloaded file:
procedure TWebModule1.WebModule1GetFileActionAction(Sender: TObject;
Request: TWebRequest; Response: TWebResponse; var Handled: Boolean);
var
lStream: TMemoryStream;
lFilename: string;
begin
lFilename := Request.QueryFields.Values['filename'];
lStream := TMemoryStream.Create;
lStream.LoadFromFile('.\Docs\' + lFilename);
lStream.Position := 0;
Response.ContentStream := lStream;
Response.ContentType := 'application/pdf';
Response.SetCustomHeader('Content-Disposition',
Format('attachment; filename="%s"', [lFilename]));
end;
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.