11#!/usr/bin/env python3
22"""
3- Upload a file to WebDAV server.
3+ Upload a directory to WebDAV server.
44
5- Usage: ./upload-webdav.py <local_file > <remote_path > --url <webdav_url> --user <username> --pass <password>
5+ Usage: ./upload-webdav.py <local_dir > <remote_dir > --url <webdav_url> --user <username> --pass <password>
66
77Example:
8- ./upload-webdav.py video.mp4 / processed/video.mp4 --url https://nextcloud.example.com/remote.php/webdav --user admin --pass secret
8+ ./upload-webdav.py ~/videos/ processed /processed --url https://nextcloud.example.com/remote.php/webdav --user admin --pass secret
99"""
1010
1111import argparse
12- import os
1312import sys
1413from pathlib import Path
1514
1615import requests
1716from requests .auth import HTTPBasicAuth
1817
1918
20- def upload_file (local_path : str , remote_path : str , webdav_url : str , username : str , password : str ) -> bool :
21- """Upload a file to WebDAV server."""
19+ def create_folder (webdav_url : str , remote_path : str , username : str , password : str ) -> bool :
20+ """Create a folder on WebDAV server."""
21+ webdav_url = webdav_url .rstrip ('/' )
22+ remote_path = remote_path .strip ('/' )
23+ url = f"{ webdav_url } /{ remote_path } "
2224
23- if not Path (local_path ).exists ():
24- print (f"Error: File not found: { local_path } " )
25+ try :
26+ response = requests .request (
27+ "MKCOL" ,
28+ url ,
29+ auth = HTTPBasicAuth (username , password ),
30+ )
31+ # 201 = created, 405 = already exists
32+ return response .status_code in (201 , 405 )
33+ except Exception as e :
34+ print (f"Error creating folder: { e } " )
2535 return False
2636
27- # Build the full URL
37+
38+ def upload_file (local_path : Path , remote_path : str , webdav_url : str , username : str , password : str ) -> bool :
39+ """Upload a single file to WebDAV server."""
2840 webdav_url = webdav_url .rstrip ('/' )
2941 remote_path = remote_path .lstrip ('/' )
3042 url = f"{ webdav_url } /{ remote_path } "
3143
32- file_size = Path (local_path ).stat ().st_size
33- print (f"Uploading: { local_path } " )
34- print (f"Size: { file_size / (1024 * 1024 ):.1f} MB" )
35- print (f"To: { url } " )
36- print ()
44+ file_size = local_path .stat ().st_size
45+ print (f" Uploading: { local_path .name } ({ file_size / (1024 * 1024 ):.1f} MB)" )
3746
3847 try :
3948 with open (local_path , 'rb' ) as f :
@@ -45,37 +54,88 @@ def upload_file(local_path: str, remote_path: str, webdav_url: str, username: st
4554 )
4655
4756 if response .status_code in (200 , 201 , 204 ):
48- print ("Upload successful !" )
57+ print (f" Done !" )
4958 return True
5059 else :
51- print (f"Upload failed: { response .status_code } { response .reason } " )
52- print (response .text [:500 ] if response .text else "" )
60+ print (f" Failed: { response .status_code } { response .reason } " )
5361 return False
5462
5563 except Exception as e :
56- print (f"Error: { e } " )
64+ print (f" Error: { e } " )
5765 return False
5866
5967
68+ def upload_directory (local_dir : str , remote_dir : str , webdav_url : str , username : str , password : str ) -> tuple [int , int ]:
69+ """Upload all files in a directory to WebDAV server."""
70+ local_path = Path (local_dir )
71+
72+ if not local_path .exists ():
73+ print (f"Error: Directory not found: { local_dir } " )
74+ return 0 , 0
75+
76+ if not local_path .is_dir ():
77+ print (f"Error: Not a directory: { local_dir } " )
78+ return 0 , 0
79+
80+ # Get all files
81+ files = list (local_path .glob ("*" ))
82+ files = [f for f in files if f .is_file ()]
83+
84+ if not files :
85+ print ("No files found in directory" )
86+ return 0 , 0
87+
88+ print (f"Found { len (files )} file(s) to upload" )
89+ print (f"Destination: { webdav_url } /{ remote_dir .strip ('/' )} /" )
90+ print ()
91+
92+ # Create remote directory
93+ remote_dir = remote_dir .strip ('/' )
94+ if remote_dir :
95+ print (f"Creating remote folder: { remote_dir } " )
96+ create_folder (webdav_url , remote_dir , username , password )
97+ print ()
98+
99+ # Upload each file
100+ success = 0
101+ failed = 0
102+
103+ for i , file in enumerate (files , 1 ):
104+ print (f"[{ i } /{ len (files )} ]" , end = "" )
105+ remote_path = f"{ remote_dir } /{ file .name } " if remote_dir else file .name
106+
107+ if upload_file (file , remote_path , webdav_url , username , password ):
108+ success += 1
109+ else :
110+ failed += 1
111+
112+ return success , failed
113+
114+
60115def main ():
61- parser = argparse .ArgumentParser (description = "Upload a file to WebDAV server" )
62- parser .add_argument ("local_file " , help = "Local file to upload" )
63- parser .add_argument ("remote_path " , help = "Remote path (e.g., /processed/video.mp4 )" )
116+ parser = argparse .ArgumentParser (description = "Upload a directory to WebDAV server" )
117+ parser .add_argument ("local_dir " , help = "Local directory to upload" )
118+ parser .add_argument ("remote_dir " , help = "Remote directory (e.g., /processed)" )
64119 parser .add_argument ("--url" , required = True , help = "WebDAV URL" )
65120 parser .add_argument ("--user" , required = True , help = "Username" )
66121 parser .add_argument ("--pass" , dest = "password" , required = True , help = "Password" )
67122
68123 args = parser .parse_args ()
69124
70- success = upload_file (
71- args .local_file ,
72- args .remote_path ,
125+ success , failed = upload_directory (
126+ args .local_dir ,
127+ args .remote_dir ,
73128 args .url ,
74129 args .user ,
75130 args .password
76131 )
77132
78- sys .exit (0 if success else 1 )
133+ print ()
134+ print ("=" * 40 )
135+ print (f"Upload complete: { success } succeeded, { failed } failed" )
136+ print ("=" * 40 )
137+
138+ sys .exit (0 if failed == 0 else 1 )
79139
80140
81141if __name__ == "__main__" :
0 commit comments