Recent

Author Topic: Best practice for file management in Downloads folder  (Read 4785 times)

bobonwhidbey

  • Hero Member
  • *****
  • Posts: 592
    • Double Dummy Solver - free download
Best practice for file management in Downloads folder
« on: August 02, 2015, 03:32:31 pm »
My app downloads files from the web into the Windows Downloads folder. I control the file name. My general philosophy is: if my app  creates a temporary work file, it's my app's responsibility to delete that file. Something like this:
Code: [Select]
  MyFile := GetDowloadsFolder+'MyAppTemp.txt';
  If FileExists(MyFile) then begin
     DeleteFile(MyFile);
     Sleep(1000); // this seems to be necessary
   end;
  ...download MyFile from the web
On the other hand, even though I've used a unique file name (that includes my app's name) it's possible that some other app has used the same file name.In that case, I would have deleted a file that I should not have.

Is there a better, more generally accepted practice?
Lazarus 3.0RC2, FPC 3.2.2 x86_64-win64-win32/win64

Leledumbo

  • Hero Member
  • *****
  • Posts: 8757
  • Programming + Glam Metal + Tae Kwon Do = Me
Re: Best practice for file management in Downloads folder
« Reply #1 on: August 02, 2015, 03:58:02 pm »

bylaardt

  • Sr. Member
  • ****
  • Posts: 309
Re: Best practice for file management in Downloads folder
« Reply #2 on: August 02, 2015, 04:06:59 pm »
I save my download files in a subfolder in my app install folder.
I do the same with my temp files, themes or downloaded libs: i use zeos with multiple possibilities of DB access  and i need download the libs to access when not installed on system(32, 64bits... Mysql, SQLite, mariadb, Postgres...).
another usual practice is create a temp subfolder on the temp dir (or a temp as leledumbo says), if you will delete all created/downloaded files when you close your program.  This is not recommended if you will storage reusable data.

lazjump

  • Jr. Member
  • **
  • Posts: 61
Re: Best practice for file management in Downloads folder
« Reply #3 on: August 02, 2015, 04:35:17 pm »
If you need a way to know if a file in the temp foler is yours or not, perhaps you could use a file prefix and suffix, where one of them is a hash value.

Example:

The original file name: 'resource.txt'

1. Give a prefix to the file name. The prefix is a fixed value you always use. Let's say the prefix is '3928'

So the file name become: '3928resource'

2. Compute the hash of the file name. You could use any hash algorithm. In this example we use CRC32. The CRC32 of 3928resource is '6B194CB2'

3. Append the hash to the file name.

The filename become '3928resource6B194CB2.txt'

Now each time you want to find your files, you will need to find files beginning with '3928'.

And then you extract the last 8 characters (excluding the extension) as the saved hash value. After that you compute the hash of the filename minus the last 8 characters. If the saved hash and the computed hash matched, then you can be sure that it is your file.
I thought Delphi was expensive until I learned the price of ExtJS

Thaddy

  • Hero Member
  • *****
  • Posts: 14377
  • Sensorship about opinions does not belong here.
Re: Best practice for file management in Downloads folder
« Reply #4 on: August 03, 2015, 08:37:40 am »
Well best practice under Windows is using Windows best practice as described by Microsoft, isn't it?
So put your temp files where they belong, in the temp directory of the current user:
%HOMEDRIVE%\Users\%USERNAME%\AppData\Local\Temp

The ratio is that you own these files anyway and can safely delete all of them.
You have to provide for some exception handling in case a file is in use.

there should be a function like this somewhere:
Code: [Select]
function GetTempDirectory:string;
var
 b:array[0..MAX_PATH] of char;
begin
  GetTempPath(MAX_PATH,b);
  SetString(Result,b,strlen(b));
end;

you can also expand it like this, but the first option maybe better:
Code: [Select]
  function GetUserTempDir:string;
  var i:integer;
  begin
    Setlength(Result,MAX_PATH);
    i := ExpandEnvironmentStrings('%HOMEDRIVE%\users\%USERNAME%\appdata\local\temp',PChar(Result),MAX_PATH);
    Setlength(Result,i);
  end;
« Last Edit: August 03, 2015, 09:42:28 am by Thaddy »
Object Pascal programmers should get rid of their "component fetish" especially with the non-visuals.

bobonwhidbey

  • Hero Member
  • *****
  • Posts: 592
    • Double Dummy Solver - free download
Re: Best practice for file management in Downloads folder
« Reply #5 on: August 03, 2015, 04:51:59 pm »
Yes - I am trying to find out Windows's best practice. In my case, I have no control over where the file is stored. The web site downloads it to the Downloads folder. My app creates the filename. The web site stores that file in the Downloads folder.

I think the gist of all replies is that I should come up with a random/unique prefix and/or suffix to the file name - and not worry any more about deleting someone else's file.
Lazarus 3.0RC2, FPC 3.2.2 x86_64-win64-win32/win64

Thaddy

  • Hero Member
  • *****
  • Posts: 14377
  • Sensorship about opinions does not belong here.
Re: Best practice for file management in Downloads folder
« Reply #6 on: August 03, 2015, 06:33:46 pm »
No, you have control over your user space. How are you extracting? By code (from fpc's libs) or by calling an external application like unzip or 7zip?
Object Pascal programmers should get rid of their "component fetish" especially with the non-visuals.

bobonwhidbey

  • Hero Member
  • *****
  • Posts: 592
    • Double Dummy Solver - free download
Re: Best practice for file management in Downloads folder
« Reply #7 on: August 03, 2015, 06:49:40 pm »
I use ShellExecute to send a URL with parameters. One of the parameters is a filename. The web site sends the desired file with the given filename TO the Downloads folder.
Lazarus 3.0RC2, FPC 3.2.2 x86_64-win64-win32/win64

Thaddy

  • Hero Member
  • *****
  • Posts: 14377
  • Sensorship about opinions does not belong here.
Re: Best practice for file management in Downloads folder
« Reply #8 on: August 04, 2015, 09:48:45 am »
Maybe this works for you? You can copy the function to your code.
Note maybe you want to write to a file stream instead. The buffer is a bit small, but you get the idea.
But this was laying around.
Code: [Select]
program wget;

{$APPTYPE CONSOLE}
uses
{$IFNDEF FPC}
 Types,
{$ENDIF}
 Sysutils,
 WinInet;

function GetUrlContent(const Url: string): string;
var
  NetHandle: HINTERNET;
  UrlHandle: HINTERNET;
  Buffer: array[0..1024] of Char;
  BytesRead: dWord;
begin
  Result := '';
  NetHandle := InternetOpen('Whatever', INTERNET_OPEN_TYPE_PRECONFIG, nil, nil, 0);

  if Assigned(NetHandle) then
  begin
    UrlHandle := InternetOpenUrl(NetHandle, PChar(Url), nil, 0, INTERNET_FLAG_RELOAD, 0);

    if Assigned(UrlHandle) then
      { UrlHandle valid? Proceed with download }
    begin
      FillChar(Buffer, SizeOf(Buffer), 0);
      repeat
        Result := Result + Buffer;
        FillChar(Buffer, SizeOf(Buffer), 0);
        InternetReadFile(UrlHandle, @Buffer, SizeOf(Buffer), BytesRead);
      until BytesRead = 0;
      InternetCloseHandle(UrlHandle);
    end
    else
      { UrlHandle is not valid. Raise an exception. }
      raise Exception.CreateFmt('Cannot open URL %s', [Url]);

    InternetCloseHandle(NetHandle);
  end
  else
    { NetHandle is not valid. Raise an exception }
    raise Exception.Create('Unable to initialize Wininet');
end;

begin
  if ParamCount = 2 then
    writeln(GetUrlContent(ParamStr(1)))
  else
    writeln('use: wget <url>');
  readln;
end.
« Last Edit: August 04, 2015, 10:17:58 am by Thaddy »
Object Pascal programmers should get rid of their "component fetish" especially with the non-visuals.

 

TinyPortal © 2005-2018