使用 FoxPro 下载文件 (HTTP)

发布于 2024-12-21 16:29:27 字数 347 浏览 2 评论 0原文

今天有人向我寻求有关 FoxPro 问题的帮助,有关如何通过 HTTP 下载文件。

我发现了两件事:一个是付费 ActiveX,另一个是 另一个需要 libcurl。

有没有一种方法可以做到这一点,而不需要任何额外的东西(VFP 8),比如Java中的HttpURLConnection?例如通过使用 Microsoft.XMLHTTP

Today I was asked for help with a FoxPro issue, about how to download a file via HTTP.

I found two things: one was a paid ActiveX, and the other one requires libcurl.

Is there a way to do that without anything additional (VFP 8), something like HttpURLConnection in Java? For example by using Microsoft.XMLHTTP

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

花桑 2024-12-28 16:29:27

两个有效的片段,不需要额外的文件/dll/flls/等。

Local loRequest, lcUrl, lcFilename

lcUrl = "http://example.com/foo.zip"
lcFilename = "C:\Temp\PSV.zip"

loRequest = Createobject('MsXml2.XmlHttp')
loRequest.Open("GET",lcUrl,.F.)
loRequest.Send()
StrToFile(loRequest.ResponseBody,lcFilename)

lox = CREATEOBJECT("inetctls.inet")
lcSuff = lox.OpenURL("http://whatever.co.uk/suff.htm")
STRTOFILE(lcStuff, "c:\data\myfile.htm")

(取自此处

Two snippets that work, and require no additional files/dlls/flls/etc.

Local loRequest, lcUrl, lcFilename

lcUrl = "http://example.com/foo.zip"
lcFilename = "C:\Temp\PSV.zip"

loRequest = Createobject('MsXml2.XmlHttp')
loRequest.Open("GET",lcUrl,.F.)
loRequest.Send()
StrToFile(loRequest.ResponseBody,lcFilename)

and

lox = CREATEOBJECT("inetctls.inet")
lcSuff = lox.OpenURL("http://whatever.co.uk/suff.htm")
STRTOFILE(lcStuff, "c:\data\myfile.htm")

(taken from here)

云朵有点甜 2024-12-28 16:29:27

是我的 HttpClient.prg 文件(仅支持 GET 响应):

#define INTERNET_OPEN_TYPE_PRECONFIG_WITH_NO_AUTOPROXY 4

#define REQ_STATE_UNINITIALIZED 0 && open()has not been called yet.
#define REQ_STATE_LOADING       1 && send()has not been called yet.
#define REQ_STATE_LOADED        2 && send() has been called, and headers and status are available.
#define REQ_STATE_INTERACTIVE   3 && Downloading; responseText holds partial data.
#define REQ_STATE_COMPLETED     4 && The operation is complete.

DEFINE CLASS HttpClientRequest As Custom
  readystate=REQ_STATE_UNINITIALIZED
  Protocol=NULL
  Url=NULL
  requestBody=NULL
  responseBody=NULL

  PROCEDURE Open(tcProtocol, tcUrl)
    IF this.readystate != REQ_STATE_UNINITIALIZED
      ERROR "HttpClientRequest is already opened."
    ENDIF
    IF VARTYPE(m.tcProtocol)!="C" OR VARTYPE(m.tcUrl)!="C" 
      ERROR "Invalid type or count of parameters."
    ENDIF
    IF NOT INLIST(m.tcProtocol,"GET")
      ERROR "Unsupported or currently not implemented protocol type."
    ENDIF
    this.Protocol = m.tcProtocol
    this.Url = m.tcUrl
    this.readystate = REQ_STATE_LOADING
  ENDPROC

  PROCEDURE Send(tcBody)
    IF this.readystate != REQ_STATE_LOADING
      ERROR "HttpClientRequest is not in initialized state."
    ENDIF
    IF PCOUNT()=0
      m.tcBody=NULL
    ENDIF
    IF this.Protocol=="GET" AND (NOT ISNULL(m.tcBody))
      ERROR "Invalid type or count of parameters."
    ENDIF
    this.requestBody = m.tcBody
    this.readystate = REQ_STATE_LOADED


    DECLARE integer InternetOpen IN "wininet.dll" ;
      string @ lpszAgent, ;
      integer dwAccessType, ;
      string @ lpszProxyName, ;
      string @ lpszProxyBypass, ;
      integer dwFlags
    DECLARE integer InternetCloseHandle IN "wininet.dll" ;
      integer hInternet
    DECLARE integer InternetCanonicalizeUrl IN "wininet.dll" ;
      string @ lpszUrl, ;
      string @ lpszBuffer, ;
      integer @ lpdwBufferLength, ;
      integer dwFlags
    DECLARE integer InternetOpenUrl IN "wininet.dll" ;
      integer hInternet, ;
      string @ lpszUrl, ;
      string @ lpszHeaders, ;
      integer dwHeadersLength, ;
      integer dwFlags, ;
      integer dwContext
    DECLARE integer InternetReadFile IN "wininet.dll" ;
      integer hFile, ;
      string @ lpBuffer, ;
      integer dwNumberOfBytesToRead, ;
      integer @ lpdwNumberOfBytesRead

    LOCAL m.hInternet,lcUrl,lnUrlLen,m.hInternetFile,lcBuffer,lnBufferLen,lnReaded
    m.hInternet = InternetOpen("a.k.d. HttpClientRequest for Visual FoxPro", ;
                               INTERNET_OPEN_TYPE_PRECONFIG_WITH_NO_AUTOPROXY, ;
                               NULL, NULL, 0)
    this.responseBody = ""
    IF m.hInternet != 0
      m.lnUrlLen = LEN(this.Url)*8
      m.lcUrl = REPLICATE(CHR(0),m.lnUrlLen)
      InternetCanonicalizeUrl(this.Url, @lcUrl, @lnUrlLen, 0)
      m.hInternetFile = InternetOpenUrl(m.hInternet, @lcUrl, NULL, -1, 0, 0)
      IF m.hInternetFile != 0
        m.lnBufferLen = 10240
        DO WHILE .T.
           m.lcBuffer = REPLICATE(CHR(0),m.lnBufferLen)
           m.lnReaded = 0
           IF NOT (0!=InternetReadFile(m.hInternetFile, @lcBuffer, m.lnBufferLen, @lnReaded) AND m.lnReaded>0)
             EXIT
           ENDIF
          this.responseBody = this.responseBody + LEFT(m.lcBuffer,m.lnReaded)
          this.readystate = REQ_STATE_INTERACTIVE
        ENDDO
        InternetCloseHandle(m.hInternetFile)
      ENDIF
      InternetCloseHandle(m.hInternet)
    ENDIF
    this.readystate = REQ_STATE_COMPLETED
  ENDPROC
ENDDEFINE

GET 请求的用法:

Local HttpClient
m.HttpClient = NEWOBJECT("HttpClientRequest","httpclient.prg")
m.HttpClient.Open("GET","http://servername/path/resourcename")
m.HttpClient.Send()

在上述代码之后执行包含在 m.HttpClient.responseBody 属性中的服务器响应,您可以将值存储到文件中,或者例如将图片存储到 Image 对象的 PictureVal 属性中:

STRTOFILE(m.HttpClient.responseBody,"c:\filename");

m.myform.AddObject("myimg",""image")
m.myform.myimg.PictureVal=m.HttpClient.responseBody

Is a my HttpClient.prg file (only GET response supported):

#define INTERNET_OPEN_TYPE_PRECONFIG_WITH_NO_AUTOPROXY 4

#define REQ_STATE_UNINITIALIZED 0 && open()has not been called yet.
#define REQ_STATE_LOADING       1 && send()has not been called yet.
#define REQ_STATE_LOADED        2 && send() has been called, and headers and status are available.
#define REQ_STATE_INTERACTIVE   3 && Downloading; responseText holds partial data.
#define REQ_STATE_COMPLETED     4 && The operation is complete.

DEFINE CLASS HttpClientRequest As Custom
  readystate=REQ_STATE_UNINITIALIZED
  Protocol=NULL
  Url=NULL
  requestBody=NULL
  responseBody=NULL

  PROCEDURE Open(tcProtocol, tcUrl)
    IF this.readystate != REQ_STATE_UNINITIALIZED
      ERROR "HttpClientRequest is already opened."
    ENDIF
    IF VARTYPE(m.tcProtocol)!="C" OR VARTYPE(m.tcUrl)!="C" 
      ERROR "Invalid type or count of parameters."
    ENDIF
    IF NOT INLIST(m.tcProtocol,"GET")
      ERROR "Unsupported or currently not implemented protocol type."
    ENDIF
    this.Protocol = m.tcProtocol
    this.Url = m.tcUrl
    this.readystate = REQ_STATE_LOADING
  ENDPROC

  PROCEDURE Send(tcBody)
    IF this.readystate != REQ_STATE_LOADING
      ERROR "HttpClientRequest is not in initialized state."
    ENDIF
    IF PCOUNT()=0
      m.tcBody=NULL
    ENDIF
    IF this.Protocol=="GET" AND (NOT ISNULL(m.tcBody))
      ERROR "Invalid type or count of parameters."
    ENDIF
    this.requestBody = m.tcBody
    this.readystate = REQ_STATE_LOADED


    DECLARE integer InternetOpen IN "wininet.dll" ;
      string @ lpszAgent, ;
      integer dwAccessType, ;
      string @ lpszProxyName, ;
      string @ lpszProxyBypass, ;
      integer dwFlags
    DECLARE integer InternetCloseHandle IN "wininet.dll" ;
      integer hInternet
    DECLARE integer InternetCanonicalizeUrl IN "wininet.dll" ;
      string @ lpszUrl, ;
      string @ lpszBuffer, ;
      integer @ lpdwBufferLength, ;
      integer dwFlags
    DECLARE integer InternetOpenUrl IN "wininet.dll" ;
      integer hInternet, ;
      string @ lpszUrl, ;
      string @ lpszHeaders, ;
      integer dwHeadersLength, ;
      integer dwFlags, ;
      integer dwContext
    DECLARE integer InternetReadFile IN "wininet.dll" ;
      integer hFile, ;
      string @ lpBuffer, ;
      integer dwNumberOfBytesToRead, ;
      integer @ lpdwNumberOfBytesRead

    LOCAL m.hInternet,lcUrl,lnUrlLen,m.hInternetFile,lcBuffer,lnBufferLen,lnReaded
    m.hInternet = InternetOpen("a.k.d. HttpClientRequest for Visual FoxPro", ;
                               INTERNET_OPEN_TYPE_PRECONFIG_WITH_NO_AUTOPROXY, ;
                               NULL, NULL, 0)
    this.responseBody = ""
    IF m.hInternet != 0
      m.lnUrlLen = LEN(this.Url)*8
      m.lcUrl = REPLICATE(CHR(0),m.lnUrlLen)
      InternetCanonicalizeUrl(this.Url, @lcUrl, @lnUrlLen, 0)
      m.hInternetFile = InternetOpenUrl(m.hInternet, @lcUrl, NULL, -1, 0, 0)
      IF m.hInternetFile != 0
        m.lnBufferLen = 10240
        DO WHILE .T.
           m.lcBuffer = REPLICATE(CHR(0),m.lnBufferLen)
           m.lnReaded = 0
           IF NOT (0!=InternetReadFile(m.hInternetFile, @lcBuffer, m.lnBufferLen, @lnReaded) AND m.lnReaded>0)
             EXIT
           ENDIF
          this.responseBody = this.responseBody + LEFT(m.lcBuffer,m.lnReaded)
          this.readystate = REQ_STATE_INTERACTIVE
        ENDDO
        InternetCloseHandle(m.hInternetFile)
      ENDIF
      InternetCloseHandle(m.hInternet)
    ENDIF
    this.readystate = REQ_STATE_COMPLETED
  ENDPROC
ENDDEFINE

Usage for GET requests:

Local HttpClient
m.HttpClient = NEWOBJECT("HttpClientRequest","httpclient.prg")
m.HttpClient.Open("GET","http://servername/path/resourcename")
m.HttpClient.Send()

After above code is executed server response contained in m.HttpClient.responseBody property and you can store value into file or for example for pictures into PictureVal property of Image object:

STRTOFILE(m.HttpClient.responseBody,"c:\filename");

m.myform.AddObject("myimg",""image")
m.myform.myimg.PictureVal=m.HttpClient.responseBody
镜花水月 2024-12-28 16:29:27

考虑使用 West Wind Web Connect。这是一个框架,允许您编写可从 Web 访问的 VFP 应用程序。

Look into using West Wind Web Connect. This is a framework that will allow you to write VFP application that are accessible from the web.

不再让梦枯萎 2024-12-28 16:29:27

您可以在 VFP 中完成此操作,但需要注册 Windows DLL 以打开连接句柄,并进行调用以获取数据。

另一种选择是使用自动化,例如使用 Internet Explorer。您可以从 VFP 中创建一个 ie 对象,并调用其方法来打开给定的 URL,等待其“就绪状态”完成,然后查看内容。至于试图获取需要URL参数字符串的东西,你可以添加这些没有问题,但如果它需要POST变量,那就要多费点力气了。

正如 Jerry 所提到的,West-Wind 工具非常强大,而且 Rick Strahl 从……我记得大约 1993 年就开始这样做了。他的另一个工具是 wwIPTools.DLL,它提供了更多功能。

You can do it in VFP, but it requires registering the Windows DLLs to open connection handles, and make calls to get data.

Another option is to use automation, such as with Internet Explorer. You can create an ie object from within VFP, and invoke its methods to open a given URL, wait until it's "Ready State" is complete, then look at the content. As for trying to get things that require URL parameter strings, you can add those no problem, but if it requires POST variables, that is a little more effort.

As mentioned by Jerry, the West-Wind tools are quite powerful and Rick Strahl has been doing it since... about 1993 that I remember. His other tool is specifically wwIPTools.DLL that offers even more features.

旧街凉风 2024-12-28 16:29:27

您还可以查看 Craig Boyd 的免费 VFPConnection 库,他还有一个优秀的免费 JSON 库。

You could also look at Craig Boyd's free VFPConnection library, he also has an excellent free JSON library.

乱了心跳 2024-12-28 16:29:27

选项 1

Declare Integer URLDownloadToFile In urlmon.dll As _apiURLDownloadToFile;
Integer pCaller, ;
String  szURL, ;
String  szFileName, ;
Integer dwReserved, ;
Integer lpfnCB

首先确保从缓存中清除文件:

Declare Integer DeleteUrlCacheEntry In wininet.dll As _apiDeleteUrlCacheEntry ;
    String  lpszUrlName

或者在 URL 末尾添加随机参数,例如“?somerandomvalue”。

选项2:

Declare Integer InternetOpen In wininet.dll As _apiInternetOpen ;
    String  lpszAgent, ;
    Integer dwAccessType, ;
    String  lpszProxy, ;
    String  lpszProxyBypass, ;
    Integer dwFlags

Declare Integer InternetOpenUrl In wininet.dll As _apiInternetOpenUrl ;
    Integer hInternet,;
    String  lpszUrl,;
    String  lpszHeaders,;
    Integer dwHeadersLength,;
    Integer dwFlags,;
    Integer dwContext

Declare Integer InternetReadFile In wininet.dll As _apiInternetReadFile ;
    Integer hFile, ;
    String  @lpBuffer, ;
    Integer dwNumberOfBytesToRead, ;
    Integer @lpdwNumberOfBytesRead

Declare Integer InternetCloseHandle In wininet.dll As _apiInternetCloseHandle ;
    Integer hInternet

函数的正确使用可以在MSDN上找到。

PS:你错过了这个:http://curl.haxx.se/libcurl/foxpro/

Option 1:

Declare Integer URLDownloadToFile In urlmon.dll As _apiURLDownloadToFile;
Integer pCaller, ;
String  szURL, ;
String  szFileName, ;
Integer dwReserved, ;
Integer lpfnCB

Just make shure to clear the file from the cache first:

Declare Integer DeleteUrlCacheEntry In wininet.dll As _apiDeleteUrlCacheEntry ;
    String  lpszUrlName

Or add a random parameter at the end of the url, like "?somerandomvalue" for example.

Option 2:

Declare Integer InternetOpen In wininet.dll As _apiInternetOpen ;
    String  lpszAgent, ;
    Integer dwAccessType, ;
    String  lpszProxy, ;
    String  lpszProxyBypass, ;
    Integer dwFlags

Declare Integer InternetOpenUrl In wininet.dll As _apiInternetOpenUrl ;
    Integer hInternet,;
    String  lpszUrl,;
    String  lpszHeaders,;
    Integer dwHeadersLength,;
    Integer dwFlags,;
    Integer dwContext

Declare Integer InternetReadFile In wininet.dll As _apiInternetReadFile ;
    Integer hFile, ;
    String  @lpBuffer, ;
    Integer dwNumberOfBytesToRead, ;
    Integer @lpdwNumberOfBytesRead

Declare Integer InternetCloseHandle In wininet.dll As _apiInternetCloseHandle ;
    Integer hInternet

The proper use of the functions can be found on MSDN.

PS: You missed this one: http://curl.haxx.se/libcurl/foxpro/

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文