Recent

Author Topic: What WinAPI functions can be used to save a file to a folder at a network drive?  (Read 775 times)

Tikani93

  • Newbie
  • Posts: 4
I have a Lazarus Win32 project, where some PDF files are downoaded with HTTP client into RAM-allocated buffer as a sequence of bytes. After downloading, it should be saved to a folder at a network drive, addressed by UNC. What a function should I use?
As far as I known, only a small subset of Win32 API functions make no difference between local/remote (UNC) paths and simply works.

Fibonacci

  • Hero Member
  • *****
  • Posts: 786
  • Internal Error Hunter
Take your pick

Code: Pascal  [Select][+][-]
  1. uses Windows;
  2.  
  3. var
  4.   h: hwnd;
  5.   s: string;
  6.   byteswritten: dword;
  7.  
  8. begin
  9.   h := CreateFile('\\nas\pub\test.txt', GENERIC_WRITE, FILE_SHARE_READ, nil, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0);
  10.   s := 'hello';
  11.   WriteFile(h, s[1], length(s), byteswritten, nil);
  12.   CloseHandle(h);
  13. end.

Code: Pascal  [Select][+][-]
  1. uses Classes;
  2.  
  3. var
  4.   s: string;
  5.  
  6. begin
  7.   s := 'hello';
  8.   with TMemoryStream.Create do begin
  9.     Write(s[1], length(s));
  10.     SaveToFile('\\nas\pub\test.txt');
  11.     Free;
  12.   end;
  13. end.

Gustavo 'Gus' Carreno

  • Hero Member
  • *****
  • Posts: 1248
  • Professional amateur ;-P
Hey Y'All,

Please excuse my lill rant. And this being a rant, it's not directed at anyone in particular, so please chill.

I'm fully aware that not everyone is as gung-ho on multiplatform compatibility as I am. And, yes, sometimes you're absolutely sure your app will only be run in a single platform, so why even bother.
But I also have another principle: Please make good use of the batteries that are included in your language. Heck, this is what makes Python so enchanting. You're spoilt rotten from the massive modules/libs/frameworks that it has.

So, my main point is: Why not just use FPHHTPClient and a File Stream?

First of all it forgoes the old file management system with something a bit more modern.
Ok, sure, if you wanna do HTTPS, especially under Windows, the OpenSSL .dlls are a pain to provide. And yes, I'm aware that under Linux we are spoilt rotten because OpenSSL usually comes installed by default in all major distributions.

End of rant!

Now, for Tikani93 in particular:
Were you aware of FPHHTPClient?
Were you aware of File Streams?

One of the awesome things about the above combo is that you pass a File Stream to FPHHTPClient and BOOM, done!!
The download is saved into the file with a single line of code ( Yes, I'm not counting the instantiation and setup of both objects ).
It's easy: You pass the file stream object to the HTTP client and press a button. No need to do in memory shenanigans by hand, because it's all managed by the File Stream.

Let me know what you have to say to this, please.

Cheers,
Gus
Lazarus 3.99(main) FPC 3.3.1(main) Ubuntu 23.10 64b Dark Theme
Lazarus 3.0.0(stable) FPC 3.2.2(stable) Ubuntu 23.10 64b Dark Theme
http://github.com/gcarreno

440bx

  • Hero Member
  • *****
  • Posts: 5575
So, my main point is: Why not just use FPHHTPClient and a File Stream?
One reason could be that the same program written using FPHHTPClient will be about 8 times larger than the same program written using WinHTTP.  I personally have tested that, a simple program that takes 50k using WinHTTP takes about 400k using FPHHTPClient and, as you mentioned, the additional libraries that are not required using WinHTTP.

In addition to that, when using FPHHTPClient there is a lot more code that can wrong, potentially making debugging more laborious.  FPHHTPClient is great when everything works fine but, the additional code means additional work when something,  for whatever reason, does not work.

Libraries are double edged swords. When they work, it's great, when they don't they are usually a black hole of code that is not easy to debug for someone who isn't intimately familiar with them.

All that said, in fairness, WinHTTP has security handshaking problems that can be next to impossible to solve (in Win 7, none in Win 10).  For instance, accessing MS' website using WinHTTP is no problem at all (in Win 7 and Win 10).   Accessing this forum, i.e, the Lazarus forum, with WinHTTP is in some cases next to impossible because of mismanagement of security protocols on the Windows side (not the Lazarus server.) In Win 7 it doesn't work while the same executable works like a charm in Win 10.  That is one reason to use FPHHTPClient and, basically, the only reason I've used it.

Like everything, there are pros and cons to it.
(FPC v3.0.4 and Lazarus 1.8.2) or (FPC v3.2.2 and Lazarus v4.0rc3) on Windows 7 SP1 64bit.

Gustavo 'Gus' Carreno

  • Hero Member
  • *****
  • Posts: 1248
  • Professional amateur ;-P
Hey 440bx,

One reason could be that the same program written using FPHHTPClient will be about 8 times larger than the same program written using WinHTTP.  I personally have tested that, a simple program that takes 50k using WinHTTP takes about 400k using FPHHTPClient and, as you mentioned, the additional libraries that are not required using WinHTTP.

In addition to that, when using FPHHTPClient there is a lot more code that can wrong, potentially making debugging more laborious.  FPHHTPClient is great when everything works fine but, the additional code means additional work when something,  for whatever reason, does not work.

Libraries are double edged swords. When they work, it's great, when they don't they are usually a black hole of code that is not easy to debug for someone who isn't intimately familiar with them.

All that said, in fairness, WinHTTP has security handshaking problems that can be next to impossible to solve (in Win 7, none in Win 10).  For instance, accessing MS' website using WinHTTP is no problem at all (in Win 7 and Win 10).   Accessing this forum, i.e, the Lazarus forum, with WinHTTP is in some cases next to impossible because of mismanagement of security protocols on the Windows side (not the Lazarus server.) In Win 7 it doesn't work while the same executable works like a charm in Win 10.  That is one reason to use FPHHTPClient and, basically, the only reason I've used it.

Like everything, there are pros and cons to it.

First and foremost, I must thank you, very much, for taking my rant and giving a, rather, thoughtful consideration and rebuke.

Secondly, I need to thank you for your experimentation in this aspect, especially with the MS/Forum shenanigans under Windows versions. This gives the community at large some answers that may have confounded them.

Thirdly, more thanks due to the fact that some of the stuff you mention about program size, I wasn't really aware of and it's a welcome piece of knowledge to know !!

Finally, I do have to agree the "Your mileage may vary" is quite pertinent in this case!!

This has also brought back the memory of a problem that I've got when using the internet via mobile tethering when using FPHTTPClient, where the download is just dropped at about 70% of completion.
I need to understand if this is a specific issue with FPHTTPClient, or if it's a problem specific to my own phone's tethering. I'll need to conduct some experiments with either Indy or Synapse.

Cheers,
Gus
« Last Edit: June 22, 2025, 08:28:45 pm by Gustavo 'Gus' Carreno »
Lazarus 3.99(main) FPC 3.3.1(main) Ubuntu 23.10 64b Dark Theme
Lazarus 3.0.0(stable) FPC 3.2.2(stable) Ubuntu 23.10 64b Dark Theme
http://github.com/gcarreno

440bx

  • Hero Member
  • *****
  • Posts: 5575
You're welcome.

Another thing I forgot to mention is documentation. 

There is a page for fphttpclient:
https://wiki.freepascal.org/fphttpclient
which does give some information about how to use fphttpclient but, I have not seen a complete list of the methods it provides along with whatever it is they do.  IOW, using fphttpclient requires a bit of guesswork, reading examples and reading its implementation.  Consequently, there is no documentation when one way (synchronous/asynchronous) or another should be used.  e.g, the method Get has 4 overloads and nowhere does it say when or why one of them is preferred over the other.

Contrast that with WinHTTP that has well organized, full documentation.  All it takes is reading the documentation to know what is available.  Though, in that respect, finding an asynchronous example is not easy (it definitely should be easier.)

The one thing fphttpclient has over WinHTTP is that, if the security dlls it needs are there, it seems quite reliable.  Can't says that for WinHTTP which under Win 7 (and likely prior versions) can be next to impossible to get it to work because of configuration problems.  Works great on Win 10 though but, not everyone in the world run Win 10 (for good reason too.)
(FPC v3.0.4 and Lazarus 1.8.2) or (FPC v3.2.2 and Lazarus v4.0rc3) on Windows 7 SP1 64bit.

PascalDragon

  • Hero Member
  • *****
  • Posts: 6035
  • Compiler Developer
So, my main point is: Why not just use FPHHTPClient and a File Stream?

Maybe the NAS of the user does not provide a HTTP interface? Maybe using SMB is simply much more transparent and flexible? For example you can simply mount the file system and have it be a transparent part of the file system (be it somewhere in the /-structure of *nix or a drive letter on Windows). Also modifying parts of a file and working with large files is much more simpler (or even possible) with SMB compared to HTTP.

On the Pascal side of things you can also simply use TFileStream in this case (which on Windows encapsulates the mentioned CreateFile and the related APIs).

When working with files in the local network I would always pick SMB instead of HTTP simply due the restrictions of the later and the flexibility of the former.

 

TinyPortal © 2005-2018