我正在制作一个小型服务器类型的应用程序。
在网络浏览器中,我希望用户输入服务器地址并登录,然后我的服务器必须返回服务器上存在的文件的路径。该文件必须在用户的本地计算机上运行(这些是小的 Excel 文件,因此它可能会很快运行)。
有可能吗?我必须先下载文件然后运行它吗?
该文件应在登录后自动运行,因此我的服务器必须将文件发送到客户端计算机并在客户端计算机上运行。
你能给我看一个小例子吗?
PS 我使用 Indy 组件,但如果有人有更好的想法,我愿意接受建议。
您所要求的在 HTTP 中在技术上是可行的,因为对任何 HTTP 请求的响应都可以是实际的 Excel 文件。例如:
使用 HTTP 身份验证:
procedure TMyForm.IdHTTPServer1CommandGet(AContext: TIdContext; ARequestInfo: TIdHTTPRequestInfo; AResponseInfo: TIdHTTPResponseInfo);
begin
if ARequestInfo.Document = '/myfile.xlsx' then
begin
if not ARequestInfo.AuthExists then
begin
AResponseInfo.AuthRealm := 'myserver';
Exit;
end;
if not UserIsAuthenticated(ARequestInfo.AuthUsername, ARequestInfo.AuthPassword) then
begin
AResponseInfo.ResponseNo := 403;
Exit;
end;
case ARequestInfo.CommandType of
hcGET:
begin
AResponseInfo.SmartServeFile(AContext, ARequestInfo, '<path>\myfile.xlsx');
end;
hcHEAD:
begin
AResponseInfo.ContentType := IdHTTPServer1.MIMETable.GetFileMIMEType('myfile.xlsx');
AResponseInfo.ContentLength := FileSizeByName('<path>\myfile.xlsx');
AResponseInfo.ContentDisposition := 'attachment; filename="myfile.xlsx";';
end;
else
AResponseInfo.ResponseNo := 405;
end;
end else
begin
AResponseInfo.ResponseNo := 404;
end;
end;
使用 HTML 网络表单身份验证:
索引.html
<html>
<head>
<title>login</title>
</head>
<body>
<form action="/login" method="POST">
Username: <input type="text" name="user"><br>
Password: <input type="password" name="pswd"><br>
<input type="submit" value="Submit"> <input type="reset" value="Clear">
</form>
</body>
</html>
procedure TMyForm.IdHTTPServer1CommandGet(AContext: TIdContext; ARequestInfo: TIdHTTPRequestInfo; AResponseInfo: TIdHTTPResponseInfo);
begin
if ARequestInfo.Document = '/' then
begin
case ARequestInfo.CommandType of
hcGET, hcHEAD:
begin
AResponseInfo.ContentType := 'text/html';
if ARequestInfo.CommandType = hcGET then
AResponseInfo.ContentStream := TIdReadFileExclusiveStream.Create('<path>\index.html')
else
AResponseInfo.ContentLength := FileSizeByName('<path>\index.html');
end;
else
AResponseInfo.ResponseNo := 405;
end;
end
else if ARequestInfo.Document = '/login' then
begin
if ARequestInfo.CommandType <> hcPOST then
begin
AResponseInfo.ResponseNo := 405;
Exit;
end;
if not UserIsAuthenticated(ARequestInfo.Params.Values['user'], ARequestInfo.Params.Values['pswd']) then
begin
AResponseInfo.ResponseNo := 403;
Exit;
end;
AResponseInfo.ServeFile(AContext, '<path>\myfile.xlsx');
end else
begin
AResponseInfo.ResponseNo := 404;
end;
end;
或者:
// make sure to set TIdHTTPServer.SessionState=True...
procedure TMyForm.IdHTTPServer1CommandGet(AContext: TIdContext; ARequestInfo: TIdHTTPRequestInfo; AResponseInfo: TIdHTTPResponseInfo);
begin
if ARequestInfo.Document = '/' then
begin
case ARequestInfo.CommandType of
hcGET, hcHEAD:
begin
AResponseInfo.ContentType := 'text/html';
if ARequestInfo.CommandType = hcGET then
AResponseInfo.ContentStream := TIdReadFileExclusiveStream.Create('<path>\index.html')
else
AResponseInfo.ContentLength := FileSizeByName('<path>\index.html');
end;
else
AResponseInfo.ResponseNo := 405;
end;
end
else if ARequestInfo.Document = '/login' then
begin
if ARequestInfo.CommandType <> hcPOST then
begin
AResponseInfo.ResponseNo := 405;
Exit;
end;
if ARequestInfo.Session = nil then
begin
IdHTTPServer1.CreateSession(AContext, AResponseInfo, ARequestInfo);
end;
if not UserIsAuthenticated(ARequestInfo.Params.Values['user'], ARequestInfo.Params.Values['pswd']) then
begin
AResponseInfo.Session.Content.Values['AuthOK'] := 'no';
AResponseInfo.ResponseNo := 403;
Exit;
end;
AResponseInfo.Session.Content.Values['AuthOK'] := 'yes';
//AResponseInfo.Redirect('/myfile.xlsx');
AResponseInfo.ResponseNo := 303;
AResponseInfo.Location := '/myfile.xlsx';
end
else if ARequestInfo.Document = '/myfile.xlsx' then
begin
if ARequestInfo.AuthExists then
begin
if ARequestInfo.Session = nil then
begin
IdHTTPServer1.CreateSession(AContext, AResponseInfo, ARequestInfo);
end;
ARequestInfo.Session.Content.Values['AuthOK'] := iif(UserIsAuthenticated(ARequestInfo.AuthUsername, ARequestInfo.AuthPassword), 'yes', 'no');
end;
if (ARequestInfo.Session = nil) or (ARequestInfo.Session.Content.IndexOf('AuthOK') = -1) then
begin
//AResponseInfo.Redirect('/');
AResponseInfo.ResponseNo := 303;
AResponseInfo.Location := '/';
Exit;
end;
if ARequestInfo.Session.Content.Values['AuthOK'] <> 'yes' then
begin
AResponseInfo.ResponseNo := 403;
Exit;
end;
case ARequestInfo.CommandType of
hcGET:
begin
AResponseInfo.SmartServeFile(AContext, ARequestInfo, '<path>\myfile.xlsx');
end;
hcHEAD:
begin
AResponseInfo.ContentType := IdHTTPServer1.MIMETable.GetFileMIMEType('myfile.xlsx');
AResponseInfo.ContentLength := FileSizeByName('<path>\myfile.xlsx');
AResponseInfo.ContentDisposition := 'attachment; filename="myfile.xlsx";';
end;
else
AResponseInfo.ResponseNo := 405;
end;
end else
begin
AResponseInfo.ResponseNo := 404;
end;
end;
然而,无论哪种方式,用户的网络浏览器都必须预先配置为.xlsx在 Excel(或他们想要的任何查看器/编辑器)中自动打开文件,或者至少提示用户是否打开文件。服务器不能强制文件自动打开,这会破坏用户的安全。