简体   繁体   中英

What do I set the download path to for users?

This is for a project where a user can download all their GitHub Gists.

This code gets the directory of the user's Download folder on their computer for files to download into. But what if the user's browser's download location is not the computer's Download folder? Maybe it's the Desktop or some random folder.

Am I supposed to check what browser the user is using and somehow get the path of where their download location is? Though a Google search says there's 200 different browsers...

Even if I was to ignore the user's browser's download location and save to the operating system's Download folder there are at least 33 according to a search.

    # Find the user's download folder
    
    # Get the operating system
    system = platform.system()

    # Set the path to save the files to the user's Download folder location
    if system == "Windows":
        save_path = os.path.join(os.environ['USERPROFILE'], 'Downloads')
    elif system == "Darwin":
        save_path = os.path.expanduser("~/Downloads")
    elif system == "Linux":
        save_path = os.path.expanduser("~/Downloads")

on windows to get the path of the Downloads folder, it should be done through win32Api, specifically through SHGetKnownFolderPath , python has access to it through ctypes, the way to access this specific function is taken from Windows Special and Known Folders from python stack overflow answer. with some modifications to read c_wchar_p.

you have to pass in the GUID for the downloads folder from KNOWNFOLDERID which is "{374DE290-123F-4565-9164-39C4925E467B}" . , so you end up with the following code that works only on 64-bit python, for 32-bit you will probably have to change the argument types.

from ctypes import windll, wintypes
from ctypes import *
from uuid import UUID
from itertools import count
from functools import partial

# ctypes GUID copied from MSDN sample code
class GUID(Structure):
    _fields_ = [
        ("Data1", wintypes.DWORD),
        ("Data2", wintypes.WORD),
        ("Data3", wintypes.WORD),
        ("Data4", wintypes.BYTE * 8)
    ]

    def __init__(self, uuidstr):
        uuid = UUID(uuidstr)
        Structure.__init__(self)
        self.Data1, self.Data2, self.Data3, self.Data4[0], self.Data4[1], rest = uuid.fields
        for i in range(2, 8):
            self.Data4[i] = rest>>(8-i-1)*8 & 0xff

FOLDERID_Downloads = '{374DE290-123F-4565-9164-39C4925E467B}'

SHGetKnownFolderPath = windll.shell32.SHGetKnownFolderPath
SHGetKnownFolderPath.argtypes = [
    POINTER(GUID), wintypes.DWORD, wintypes.HANDLE, POINTER(c_char_p)]

def get_known_folder_path(uuidstr):
    pathptr = c_char_p()
    guid = GUID(uuidstr)
    if SHGetKnownFolderPath(byref(guid), 0, 0, byref(pathptr)):
        raise Exception('Whatever you want here...')
    resp = cast(pathptr,POINTER(c_wchar))
    iterator = (resp.__getitem__(i) for i in count(0))
    result = ''.join(list(iter(iterator.__next__, '\x00')))
    return result

print(get_known_folder_path(FOLDERID_Downloads))

this will return the Downloads folder location even if the user changes it through the properties, or for different languages.


on linux a similar method is to get it from $HOME/.config/user-dirs.dirs under the name of XDG_DOWNLOAD_DIR , which is changed with user settings changes.

$ grep XDG_DOWNLOAD_DIR ~/.config/user-dirs.dirs

XDG_DOWNLOAD_DIR="$HOME/Downloads"

This is obviously only the "default" location, you should allow the user to manually specify his own custom downloads path.

Using a hardcoded path is a recipe for "but it works on my machine", so just ask the OS about its path.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM