Delphi indy将文件发送到客户端并运行

时间:2018-04-27 11:19:26

标签: delphi server indy

我正在制作一个小型服务器类型的应用程序。

在Web浏览器中,我希望用户输入服务器地址并登录,然后我的服务器必须返回服务器上存在的文件的路径。该文件必须在用户的本地计算机上运行(这些是小型Excel文件,因此它可能会很快运行)。

有可能吗?我是否必须先下载文件然后运行它?

该文件应在登录后自动运行,因此我的服务器必须将文件发送到客户端计算机并在客户端计算机上运行。

你能告诉我一个小例子吗?

P.S。我使用Indy组件,但如果有人有更好的想法,我可以接受建议。

1 个答案:

答案 0 :(得分:1)

您要求的是技术上在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 webform身份验证:

的index.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;

然而,无论哪种方式,都必须事先配置用户的Web浏览器以自动打开Excel中的.xlsx文件(或他们想要的任何查看器/编辑器),或者至少提示用户是否打开文件。服务器无法强制自动打开文件,这会破坏用户的安全性。