QB64.org Forum

Active Forums => QB64 Discussion => Topic started by: xra7en on May 15, 2021, 11:24:26 am

Title: reading remote text file
Post by: xra7en on May 15, 2021, 11:24:26 am
I thought I saw a thread here awhile ago regarding this, might have been a different language.

can qb64 read a remote txtfile?

example mycoolsite.com/textfile.txt

was trying (of course unsuccessfully) the open command.

thanks guys

ps
Its the weekend, working on another goofy project.

Title: Re: reading remote text file
Post by: 191Brian on May 15, 2021, 03:36:28 pm
Pretty sure the answer is no, open only works on files local to you either on your PC or network share.
Title: Re: reading remote text file
Post by: SMcNeill on May 15, 2021, 03:55:06 pm
You can look at the QB64 wiki download program I have here, as an example, if you’re just transfering over http and not https: https://www.qb64.org/forum/index.php?topic=756.msg6455#msg6455

Basically, use _OPENCLIENT and GET to do the work:

SUB DownloadRSS (url$, file$, timelimit)
    link$ = url$
    DIM l AS _INTEGER64, lod AS _INTEGER64
 
    url2$ = RTRIM$(LTRIM$(link$))
    url4$ = RTRIM$(LTRIM$(link$))
    IF LEFT$(UCASE$(url2$), 7) = "HTTP://" THEN url4$ = MID$(url2$, 8)
    x = INSTR(url4$, "/")
    IF x THEN url2$ = LEFT$(url4$, x - 1)
    NewsClient = _OPENCLIENT("TCP/IP:80:" + url2$)
    IF NewsClient = 0 THEN EXIT FUNCTION
    e$ = CHR$(13) + CHR$(10) ' end of line characters
    url3$ = RIGHT$(url4$, LEN(url4$) - x + 1)
    x$ = "GET " + url3$ + " HTTP/1.1" + e$
    x$ = x$ + "Host: " + url2$ + e$ + e$
    PUT #NewsClient, , x$
 
    OPEN file$ FOR OUTPUT AS #1: CLOSE #1
    OPEN file$ FOR BINARY AS #1
 
    t! = TIMER ' start time
    head$ = ""
    cont_type$ = ""
    DO
        _LIMIT 20
        GET #NewsClient, , a$
        IF LTRIM$(a$) > "" THEN PUT #1, , a$
    LOOP UNTIL TIMER > t! + timelimit AND timelimit > 0 ' (in seconds)
    CLOSE #NewsClient
    CLOSE #1
END SUB
Title: Re: reading remote text file
Post by: xra7en on May 15, 2021, 04:41:17 pm
I checked the wiki with no luck, but only because I had no direction - "open" was all I knew.

This is good, I will part it out and see how it ticks!!

what I am doing is pulling a simple text file from one of my sites, I could just turn off the SSL and from what you said it should work.

Out of necessity, I wrote a "chocolatey" alternative (qb64), but much more simpler, been using it for last few years - I wanted something simple without complexity. works great. however I want a centralized DB instead of locally. So trying the old fashion text method - it works, and does not need something advanced as SQL(programing sql for remote access is an overkill for what I want). I basically just keep track of appname and link to it directly.



thanks!

I'll let you know if this works... and post a code here.
Title: Re: reading remote text file
Post by: zaadstra on May 15, 2021, 05:00:00 pm
I use(d) to do this with a shell and wget command, then open the downloaded file.
But the example from SMcNeill looks very cool! Especially the timeout will be helpful too.
Looking forward to more examples here! :-)
Title: Re: reading remote text file
Post by: SpriggsySpriggs on May 15, 2021, 05:02:43 pm
I would just use the WinAPI function sets. The easiest one is URLDownloadToFile
Title: Re: reading remote text file
Post by: xra7en on May 15, 2021, 05:18:13 pm
actually I ended up using curl like the rest of my app does. der!!!
 wget I get all kinds of security errors when I use it. Curl works good with the following command:

Code: QB64: [Select]
  1. curl -LO -k [url]

I like what McNiel has, but I cannot get it to work. returns a 0 every time. I'll have to tinker with that later. I like it better than curl or wget as it is part of qb64.
Title: Re: reading remote text file
Post by: SpriggsySpriggs on May 15, 2021, 06:29:25 pm
This doesn't require curl or any other external shell program.

Code: QB64: [Select]
  1.     Function URLDownloadToFileA%& (ByVal pCaller As Long, szURL As String, szFileName As String, Byval dwReserved As Long, Byval lpfnCB As Long)
  2.  
  3. Function FileDownload%& (URL As String, File As String)
  4.     FileDownload = URLDownloadToFileA(0, URL + Chr$(0), File + Chr$(0), 0, 0)
Title: Re: reading remote text file
Post by: xra7en on May 16, 2021, 07:40:35 am
well that worked amazing simple!! Wish I knew more about API's and how to use them in qb64

I started a progress bar question here: https://www.qb64.org/forum/index.php?topic=3913.0
obviously on larger files I would like to display something... so I know it is not locked up
Title: Re: reading remote text file
Post by: xra7en on May 16, 2021, 10:44:47 am
hmmm doesn't work all the time

example
using

Code: QB64: [Select]
  1. fn$="Git-2.31.1-64-bit.exe"
  2. url$ = "https://github.com/git-for-windows/git/releases/download/v2.31.1.windows.1/Git-2.31.1-64-bit.exe"
  3. filedownload(url$,fn$)

does nothing. no download

but works flawlessly when downloading a text file.
Title: Re: reading remote text file
Post by: SpriggsySpriggs on May 16, 2021, 10:59:54 am
If that's the case then you probably need to use a more complex API function set. I have code for this but I'm currently on my phone. I have code that tracks progress as well as downloads any file. It will be a few hours before I can get it to you, though.
Title: Re: reading remote text file
Post by: SpriggsySpriggs on May 16, 2021, 03:39:03 pm
@xra7en

This code allows for downloading of any file type and will track the progress of the download as long as it can query the webpage for the file size. You can edit it however you like for your own needs.

Code: QB64: [Select]
  1.  
  2. Const INTERNET_OPEN_TYPE_DIRECT = 1
  3.  
  4. Const INTERNET_DEFAULT_HTTP_PORT = 80
  5. Const INTERNET_DEFAULT_HTTPS_PORT = 443
  6.  
  7. Const INTERNET_SERVICE_HTTP = 3
  8.  
  9. 'Flags
  10. Const INTERNET_FLAG_SECURE = &H00800000
  11. Const INTERNET_FLAG_RELOAD = &H80000000
  12.  
  13. Const HTTP_QUERY_CONTENT_LENGTH = 5
  14.  
  15. Const TRUE = 1
  16. 'CONST FALSE = 0
  17.  
  18.     Function InternetOpen%& Alias "InternetOpenA" (ByVal lpszAgent As _Offset, Byval dwAccessType As Long, Byval lpszProxy As _Offset, Byval lpszProxyBypass As _Offset, Byval dwFlags As Long)
  19.     Function InternetConnect%& Alias "InternetConnectA" (ByVal hInternet As _Offset, Byval lpszServerName As _Offset, Byval nServerPort As Integer, Byval lpszUserName As _Offset, Byval lpszPassword As _Offset, Byval dwService As Long, Byval dwFlags As Long, Byval dwContext As _Offset)
  20.     Function HTTPOpenRequest%& Alias "HttpOpenRequestA" (ByVal hConnect As _Offset, Byval lpszVerb As _Offset, Byval lpszObjectName As _Offset, Byval lpszVersion As _Offset, Byval lpszReferrer As _Offset, Byval lpszAcceptTypes As _Offset, Byval dwFlags As Long, Byval dwContext As _Offset)
  21.     Function HTTPSendRequest%% Alias "HttpSendRequestA" (ByVal hRequest As _Offset, Byval lpszHeaders As _Offset, Byval dwHeadersLength As Long, Byval lpOptional As _Offset, Byval dwOptionalLength As Long)
  22.     Sub InternetCloseHandle (ByVal hInternet As _Offset)
  23.     Function InternetReadFile%% (ByVal hFile As _Offset, Byval lpBuffer As _Offset, Byval dwNumberOfBytesToRead As Long, Byval lpdwNumberOfBytesRead As _Offset)
  24.     Function HTTPQueryInfo%% Alias "HttpQueryInfoA" (ByVal hRequest As _Offset, Byval dwInfoLevel As Long, Byval lpBuffer As _Offset, Byval lpdwBufferLength As _Offset, Byval lpdwIndex As _Offset)
  25.  
  26.     Function GetLastError& ()
  27.     Sub SetLastError (ByVal dwErrCode As Long)
  28.     Function FormatMessage& Alias "FormatMessageA" (ByVal dwFlags As Long, Byval lpSource As Long, Byval dwMessageId As Long, Byval dwLanguageId As Long, Byval lpBuffer As _Offset, Byval nSize As Long, Byval Arguments As _Offset)
  29.  
  30. Declare CustomType Library ".\offsettostring"
  31.     Function offset_to_string$ Alias "offset_to_offset" (ByVal offset As _Offset)
  32.  
  33.     Function MAKELANGID& (ByVal p As Long, Byval s As Long)
  34.  
  35.  
  36. Screen _NewImage(480, 80, 32)
  37.  
  38. _Title "URL Downloader"
  39. _ConsoleTitle "Enter Link"
  40. Dim filename As String
  41.  
  42.     Cls
  43.     Line Input "Link: ", link
  44.     Line Input "File Name : ", filename
  45. Loop Until link <> "" And filename <> ""
  46. _Title _Title$ + " - " + Mid$(filename, _InStrRev(filename, "\") + 1)
  47.  
  48.  
  49. DownloadLink link, filename
  50.  
  51. Sub DownloadLink (URL As String, File As String)
  52.     Dim As String URLFile
  53.     URLFile = URL
  54.     Dim As _Offset hsession
  55.     hsession = InternetOpen(0, INTERNET_OPEN_TYPE_DIRECT, 0, 0, 0)
  56.     If hsession = 0 Then
  57.         Cls
  58.         Print "Error : InternetOpen", ErrorMessage(GetLastError)
  59.         InternetCloseHandle hsession
  60.         Exit Sub
  61.     End If
  62.  
  63.     Dim As _Offset httpsession
  64.     URL = Mid$(URL, InStr(URL, "/") + 2)
  65.     URL = Mid$(URL, 1, InStr(URL, "/") - 1)
  66.  
  67.     httpsession = InternetConnect(hsession, _Offset(URL), INTERNET_DEFAULT_HTTPS_PORT, 0, 0, INTERNET_SERVICE_HTTP, 0, 0)
  68.     If httpsession = 0 Then
  69.         Cls
  70.         Print "Error : Internet Connect", ErrorMessage(GetLastError)
  71.         InternetCloseHandle hsession
  72.         Exit Sub
  73.     End If
  74.  
  75.     Dim As _Offset httpRequest
  76.     Dim As String sessiontype, location, accepttypes
  77.     sessiontype = "GET" + Chr$(0)
  78.     location = Mid$(URLFile, InStr(URLFile, URL) + Len(URL)) + Chr$(0)
  79.     accepttypes = "*/*" + Chr$(0)
  80.     httpRequest = HTTPOpenRequest(httpsession, _Offset(sessiontype), _Offset(location), 0, 0, _Offset(accepttypes), INTERNET_FLAG_RELOAD Or INTERNET_FLAG_SECURE, 0)
  81.     If httpRequest = 0 Then
  82.         Cls
  83.         Print "Error : HTTPOpenRequest", ErrorMessage(GetLastError)
  84.         InternetCloseHandle hsession
  85.         Exit Sub
  86.     End If
  87.  
  88.     Dim As Long sendrequest
  89.     Dim As String headers
  90.     headers = ""
  91.     sendrequest = HTTPSendRequest(httpRequest, 0, 0, 0, 0)
  92.     If sendrequest <> TRUE Then
  93.         Cls
  94.         Print "Error : HTTPSendRequest", ErrorMessage(GetLastError)
  95.         InternetCloseHandle hsession
  96.         Exit Sub
  97.     End If
  98.  
  99.  
  100.     Dim As _Byte query
  101.     Dim As String queryinfo
  102.     queryinfo = Space$(1024)
  103.     Dim As Long querylen
  104.     querylen = Len(queryinfo) - 1
  105.  
  106.     query = HTTPQueryInfo(httpRequest, HTTP_QUERY_CONTENT_LENGTH, _Offset(queryinfo), _Offset(querylen), 0)
  107.     If query <> TRUE Then
  108.         Cls
  109.         Print "Error : HTTPQueryInfo", ErrorMessage(GetLastError)
  110.         InternetCloseHandle hsession
  111.     End If
  112.  
  113.     Dim As Long bytesToRead
  114.     bytesToRead = Val(queryinfo)
  115.  
  116.     Dim As String szBuffer
  117.     szBuffer = Space$(4097)
  118.     Dim As _Unsigned Long dwRead, bytesRead
  119.     If _FileExists(File) Then
  120.         Kill File
  121.     End If
  122.     Open File For Binary As #1
  123.     Dim As _Byte a
  124.     Dim As String filedownload
  125.     Dim As Long errr, bytesForRate
  126.     Dim x!
  127.     Dim y!
  128.     Dim Rate!
  129.     Dim As Single ratetime
  130.     Do
  131.         x! = Timer
  132.         a = InternetReadFile(httpRequest, _Offset(szBuffer), Len(szBuffer) - 1, _Offset(dwRead))
  133.         errr = GetLastError
  134.         If dwRead > 0 Then
  135.             filedownload = Mid$(szBuffer, 1, dwRead)
  136.             Put #1, , filedownload
  137.             bytesRead = bytesRead + dwRead
  138.             bytesForRate = bytesForRate + dwRead
  139.             ratetime = timeElapsedSince(x!)
  140.             If _Round(ratetime) >= 1 Then
  141.                 Rate! = (bytesForRate / ratetime) / 1024
  142.                 bytesForRate = 0
  143.             End If
  144.             Cls
  145.             Print "Downloading to " + File
  146.             If bytesToRead <> 0 Then
  147.                 Print bytesRead; "bytes downloaded of"; bytesToRead
  148.                 Print Using "###.##%"; bytesRead / bytesToRead * 100
  149.             Else
  150.                 Select Case bytesRead
  151.                     Case Is < 1024
  152.                         Print Using "   ####  B downloaded"; bytesRead
  153.                     Case Is < (1024 ^ 2) And bytesRead >= 1024
  154.                         Print Using "####.## KB downloaded"; (bytesRead / 1024)
  155.                     Case Is < (1024 ^ 3) And bytesRead >= (1024 ^ 2)
  156.                         Print Using "####.## MB downloaded"; (bytesRead / (1024 ^ 2))
  157.                     Case Is < (1024 ^ 4) And bytesRead >= (1024 ^ 3)
  158.                         Print Using "####.## GB downloaded"; (bytesRead / (1024 ^ 3))
  159.                 End Select
  160.             End If
  161.             Print "Rate="; _Round(Rate!); "KBps"
  162.             _Display
  163.         End If
  164.     Loop Until bytesRead = bytesToRead Or errr <> 0
  165.     If errr Then
  166.         Print "Error downloading file:"; errr
  167.         Close #1
  168.         InternetCloseHandle hsession
  169.         Kill File
  170.         Exit Sub
  171.     Else
  172.     End If
  173.     Close #1
  174.     InternetCloseHandle hsession
  175.     Cls
  176.     Print bytesRead; "bytes downloaded of"; bytesToRead
  177.     Print Using "###.##%"; bytesRead / bytesToRead * 100
  178.     Print "Downloaded to " + File
  179.  
  180. Function timeElapsedSince! (startTime!)
  181.     If startTime! > Timer Then startTime! = startTime! - 86400
  182.     timeElapsedSince! = Timer - startTime!
  183.  
  184. Function ErrorMessage$ (errCode As Long)
  185.     Const FORMAT_MESSAGE_ALLOCATE_BUFFER = &H00000100
  186.     Const FORMAT_MESSAGE_FROM_SYSTEM = &H00001000
  187.     Const FORMAT_MESSAGE_IGNORE_INSERTS = &H00000200
  188.  
  189.     Const LANG_NEUTRAL = &H00
  190.     Const SUBLANG_DEFAULT = &H01
  191.  
  192.     Dim As _Offset lpMsgBuf
  193.     Dim As Long msg
  194.  
  195. msg = FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER Or _
  196.                     FORMAT_MESSAGE_FROM_SYSTEM Or _
  197.                     FORMAT_MESSAGE_IGNORE_INSERTS, _
  198.                    0, _
  199.                     errCode, _
  200.                     MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), _
  201.                     _Offset(lpMsgBuf), _
  202.                    0, 0)
  203.  
  204.  
  205.     ErrorMessage = offset_to_string(lpMsgBuf)

Code: C++: [Select]
  1.  //save as offsettostring.h
  2. void *offset_to_offset(void* offset){
  3.    return offset;
  4. }
Title: Re: reading remote text file
Post by: xra7en on May 16, 2021, 08:32:12 pm
YOU KNOW you are giving a new meaning to "BASIC" LOL
Im starting to feel like I am programming in c++



thanks I'll tinker with that next week - stuck on call this week grrrrr
Title: Re: reading remote text file
Post by: SpriggsySpriggs on May 16, 2021, 08:49:08 pm
@xra7en Hahaha yeah it's basic to me but not everyone :)

It is very similar to programming in C++ because all of those functions are from C DLLs and that header file is a C++ file.
Title: Re: reading remote text file
Post by: xra7en on May 22, 2021, 04:15:43 pm
ok. been playing around with this api, fun.

keep getting this error o.O
Code: QB64: [Select]
  1. Error: HTTPOpenRequest  The data area passed to a system  call is too small


Quote
filename: npp.7.9.5.Installer.x64.exe
link: https://github.com/notepad-plus-plus/notepad-plus-plus/releases/download/v7.9.5/npp.7.9.5.Installer.x64.exe

Now this is all greek to me, however like the internal ability. so learning
Title: Re: reading remote text file
Post by: xra7en on May 22, 2021, 04:19:26 pm
trying some research:
found that this error needs to be addressed by using the
InternetCrackUrlA()

https://docs.microsoft.com/en-us/windows/win32/api/wininet/nf-wininet-internetcrackurla

apparently I have to break down the url before sending it?
Title: Re: reading remote text file
Post by: SpriggsySpriggs on May 22, 2021, 04:19:39 pm
@xra7en Just for me to do some testing:

Title: Re: reading remote text file
Post by: SpriggsySpriggs on May 22, 2021, 04:21:33 pm
In my code I gave you, my code already breaks the URL down into location and base URL. You'll see some MID$ stuff before I do some calls
Title: Re: reading remote text file
Post by: xra7en on May 22, 2021, 04:29:46 pm
oops I did not do any editing...

lemme tinker with that. I see you did break it down. I want to see if I can solved this (hints are helpful - sorta like playing portal.. point the direction but not what portal to what wall haha)
Title: Re: reading remote text file
Post by: xra7en on May 23, 2021, 04:45:06 pm
Ok dont see anything I need to change. I actually found your video on youtube - LOL. and your download worked fine. so it might be just how I am parsing the download

Which is the correct way:

download https://www.cooldownloadsite.com/download/filename.zip, filename.zip
or
https://www.cooldownloadsite.com/download, filename.zip

My curent setup is the first option.