Delphi indy отправляет файл клиенту и запускает - PullRequest
0 голосов
/ 27 апреля 2018

Я делаю небольшое приложение типа сервера.

В веб-браузере я хочу, чтобы пользователь ввел адрес сервера и логин, а затем мой сервер должен вернуть путь к файлу, который существует на сервере. Файл должен быть запущен на локальном компьютере пользователя (это небольшие файлы Excel, поэтому он, вероятно, будет работать быстро).

Возможно ли это сделать? Нужно ли сначала загружать файл, а затем запускать его?

Файл должен запускаться автоматически после входа в систему, поэтому мой сервер должен отправить файл на клиентский компьютер и запустить его на клиентском компьютере.

Можете ли вы показать мне маленький пример?

P.S. Я использую компоненты Indy, но если у кого-то есть идея получше, я открыт для предложений.

1 Ответ

0 голосов
/ 27 апреля 2018

То, что вы запрашиваете, это технически выполнимо в 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-форме:

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;

Однако, в любом случае, веб-браузер пользователя должен быть предварительно настроен на автоматическое открытие файлов .xlsx в Excel (или любом другом средстве просмотра / редакторе), или, по крайней мере, для запроса пользователю, открывать ли файлы. Сервер не может заставить файлы открываться автоматически, это было бы нарушением безопасности пользователя.

...