在delphi上使用WININET上载文件

在delphi上使用WININET上载文件,delphi,http,wininet,Delphi,Http,Wininet,我有一个delphi wininet应用程序 上周我试图发送信息以执行JSON方法,本周我试图将文件上传到web服务器。我使用了相同的代码,只是做了一些修改,但在InternetWriteFile过程执行的那一刻,该程序引发了一个异常:“Controlador no válido” 代码如下: function TFormMain.CargarArchivo(Archivo, Server: string; Username, Password: PChar; blnSSL, iftok

我有一个delphi wininet应用程序

上周我试图发送信息以执行JSON方法,本周我试图将文件上传到web服务器。我使用了相同的代码,只是做了一些修改,但在InternetWriteFile过程执行的那一刻,该程序引发了一个异常:“Controlador no válido”

代码如下:

    function TFormMain.CargarArchivo(Archivo, Server: string; Username, Password: PChar; blnSSL, iftoken: Boolean): Boolean;
    var
       Url, Header : String;
       pSession, pConnection, pRequest : HINTERNET;
       flags, dwSize, dwFlags : DWORD;
       dwError, Port : Integer;
       Escritos    : Cardinal;
    begin
       Result := false;
       pSession := InternetOpen(nil, INTERNET_OPEN_TYPE_PRECONFIG, nil, nil, 0);
       if not Assigned(pSession) then
          raise Exception.Create('InternetOpen failed. ' + WinInetErrorMsg(GetLastError));
       try
          Url := Copy(Server,pos('/Servidor',Server),length(Server));
          if blnSSL then
          begin
             Server := Copy(Server,9,pos('/Servidor',Server)-1);
             Port := INTERNET_DEFAULT_HTTPS_PORT
          end
          else
          begin
             Server := Copy(Server,8,pos('/Servidor',Server)-1);
             Server := Copy(Server,1,pos(':',Server)-1);
             Port := 8080;
          end;
          pConnection := InternetConnect(pSession, PChar(Server), port, Username, Password, INTERNET_SERVICE_HTTP, 0, 0);
          if not Assigned(pConnection) then
             raise Exception.Create('InternetConnect failed. ' + WinInetErrorMsg(GetLastError));
          try
             if blnSSL then
                flags := INTERNET_FLAG_SECURE
             else
                flags := 0;
             pRequest := HTTPOpenRequest(pConnection, 'POST', PChar(Url), nil, nil, nil, flags, 0);
             if not Assigned(pRequest) then
                raise Exception.Create('HttpOpenRequest failed. ' + WinInetErrorMsg(GetLastError));
             try
                // Set buffer size
                dwSize:=SizeOf(dwFlags);
                // Get the current flags
                if (InternetQueryOption(pRequest, INTERNET_OPTION_SECURITY_FLAGS, @dwFlags, dwSize)) then
                begin
                   // Add desired flags
                   dwFlags:=dwFlags or SECURITY_FLAG_IGNORE_UNKNOWN_CA or SECURITY_FLAG_IGNORE_CERT_CN_INVALID or SECURITY_FLAG_IGNORE_CERT_DATE_INVALID;
                   // Set new flags
                   if not(InternetSetOption(pRequest, INTERNET_OPTION_SECURITY_FLAGS, @dwFlags, dwSize)) then
                   begin
                      // Get error code
                      dwError:=GetLastError;
                      // Failure
                      MessageBox(Application.Handle, PChar(IntToStr(dwError)), PChar(Application.Title), MB_OK or MB_ICONINFORMATION);
                   end;
                end
                else
                begin
                   // Get error code
                   dwError:=GetLastError;
                   // Failure
                   MessageBox(Application.Handle, PChar(IntToStr(dwError)), PChar(Application.Title), MB_OK or MB_ICONINFORMATION);
                end;
                Header := 'Host: ' + Server + ':' + IntToStr(Port) + #13#10 +
                          'Content-Type: multipart/form-data; charset=UTF-8'#13#10;
                if iftoken then
                begin
                   Header := Header + 'auth_token: '+token+#13#10;
                   Header := Header + 'Csrf-token: no-check'#13#10;
                end;

                if not HttpAddRequestHeaders(pRequest, PChar(Header), Length(Header), HTTP_ADDREQ_FLAG_ADD) then
                   raise Exception.Create('HttpAddRequestHeaders failed. ' + WinInetErrorMsg(GetLastError));

                Parameters := TIdMultiPartFormDataStream.Create;
                Parameters.AddFile('archivo', Archivo, '');
                if not HTTPSendRequest(pRequest, nil, 0, Parameters, Parameters.Size) then
                   raise Exception.Create('HTTPSendRequest failed. ' + WinInetErrorMsg(GetLastError));

                try
                   if not InternetWriteFile(Parameters, Parameters, Parameters.Size, Escritos) then
                      raise Exception.Create('InternetWriteFile failed. ' + WinInetErrorMsg(GetLastError));
                   Result := true;
                finally
                   Parameters.Free;
                end;
             finally
                InternetCloseHandle(pRequest);
             end;
          finally
             InternetCloseHandle(pConnection);
          end;
       finally
          InternetCloseHandle(pSession);
       end;
    end;


我尝试用FTPOpenFile过程初始化文件指针,但它不起作用,因为服务器是HTTP,而不是FTP,我想。

您不能以尝试混合Indy和WinInet的方式混合它们

您正试图直接从内存发布Indy
TIdMultipartFormDataStream
对象。那是行不通的。您必须告诉
TIdMultipartFormDataStream
从输入参数生成MIME数据,然后发布该数据
TIdHTTP.Post()。在这种情况下,您必须将生成的
TIdMultipartFormDataStream
数据保存到一个单独的
TMemoryStream
(使用
TStream.CopyFrom()
方法)中,然后您可以使用WinInet发布该数据

即使如此,您的
帖子仍然会中断,因为:

  • 您没有在
    内容类型
    请求头中包含所需的
    边界
    参数(
    TIdMultipartFormDataStream
    动态生成该值),因此服务器可以正确解析MIME部分

  • 如果两者都试图发送请求的正文数据,则不能将
    HTTPSendRequest()
    InternetWriteFile()
    混合在一起。挑一个或另一个

  • 尝试类似以下内容:

    PostData := TMemoryStream.Create;
    try
      Parameters := TIdMultiPartFormDataStream.Create;
      try
        Parameters.AddFile('archivo', Archivo, '');
        PostData.CopyFrom(Parameters, 0);
        Header := 'Host: ' + Server + ':' + IntToStr(Port) + #13#10 +
                  'Content-Type: ' + Parameters.RequestContentType + #13#10;
      finally
        Parameters.Free;
      end;    
      if iftoken then
      begin
        Header := Header + 'auth_token: '+token+#13#10;
        Header := Header + 'Csrf-token: no-check'#13#10;
      end;
      if not HttpAddRequestHeaders(pRequest, PChar(Header), Length(Header), HTTP_ADDREQ_FLAG_ADD) then
        raise Exception.Create('HttpAddRequestHeaders failed. ' + WinInetErrorMsg(GetLastError));
      if not HTTPSendRequest(pRequest, nil, 0, PostData.Memory, PostData.Size) then
        raise Exception.Create('HTTPSendRequest failed. ' + WinInetErrorMsg(GetLastError));
      Result := True;
    finally
      PostData.Free;
    end;
    

    再次感谢你的帮助。我真的是处理这个组件的新手,我习惯使用INDY,因此我的组件组合。