saliacoel commited on
Commit
91286ad
·
verified ·
1 Parent(s): b988c21

Upload hfDonloder.py

Browse files
Files changed (1) hide show
  1. hfDonloder.py +178 -0
hfDonloder.py ADDED
@@ -0,0 +1,178 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # ComfyUI/custom_nodes/zip_output_to_hf.py
2
+ #
3
+ # Node: ZipOutputToHuggingFace
4
+ #
5
+ # - Zips the ComfyUI output folder
6
+ # - Uploads the zip to a Hugging Face repo
7
+ # - Returns a direct download URL as STRING
8
+
9
+ import os
10
+ import time
11
+ import zipfile
12
+ import tempfile
13
+
14
+ import folder_paths # ComfyUI's helper for paths
15
+
16
+ try:
17
+ from huggingface_hub import HfApi
18
+ except ImportError:
19
+ HfApi = None
20
+
21
+
22
+ class ZipOutputToHuggingFace:
23
+ """
24
+ Zip the ComfyUI output folder and upload the archive to Hugging Face.
25
+ """
26
+
27
+ @classmethod
28
+ def INPUT_TYPES(cls):
29
+ return {
30
+ "required": {
31
+ # Where to upload; default to your repo
32
+ "hf_repo_id": (
33
+ "STRING",
34
+ {"default": "saliacoel/MyCustomNodes"},
35
+ ),
36
+ },
37
+ "optional": {
38
+ # Hugging Face token; can be left empty if you use env vars / hf auth login
39
+ "hf_token": (
40
+ "STRING",
41
+ {
42
+ "default": "",
43
+ "multiline": False,
44
+ },
45
+ ),
46
+ # Prefix for the zip filename
47
+ "zip_name_prefix": (
48
+ "STRING",
49
+ {
50
+ "default": "comfy_output",
51
+ "multiline": False,
52
+ },
53
+ ),
54
+ # Subfolder in the repo to put the zip into
55
+ "remote_dir": (
56
+ "STRING",
57
+ {
58
+ "default": "exports",
59
+ "multiline": False,
60
+ },
61
+ ),
62
+ },
63
+ }
64
+
65
+ RETURN_TYPES = ("STRING",)
66
+ RETURN_NAMES = ("download_url",)
67
+ FUNCTION = "zip_and_upload"
68
+ CATEGORY = "utils/huggingface"
69
+ OUTPUT_NODE = True # can act as a terminal node in your graph
70
+
71
+ def zip_and_upload(
72
+ self,
73
+ hf_repo_id: str,
74
+ hf_token: str = "",
75
+ zip_name_prefix: str = "comfy_output",
76
+ remote_dir: str = "exports",
77
+ ):
78
+ # 1. Check huggingface_hub availability
79
+ if HfApi is None:
80
+ raise RuntimeError(
81
+ "huggingface_hub is not installed.\n"
82
+ "Install it in your ComfyUI environment, for example:\n"
83
+ " pip install huggingface_hub"
84
+ )
85
+
86
+ # 2. Get ComfyUI output directory
87
+ output_dir = folder_paths.get_output_directory()
88
+ if not os.path.isdir(output_dir):
89
+ raise RuntimeError(f"Output directory does not exist: {output_dir}")
90
+
91
+ # 3. Ensure there is at least one file to zip
92
+ has_files = False
93
+ for _, _, files in os.walk(output_dir):
94
+ if files:
95
+ has_files = True
96
+ break
97
+ if not has_files:
98
+ raise RuntimeError(
99
+ f"No files found in output directory: {output_dir}"
100
+ )
101
+
102
+ # 4. Create zip in a temp directory (so we don't zip the zip)
103
+ timestamp = time.strftime("%Y%m%d-%H%M%S")
104
+ safe_prefix = (zip_name_prefix or "").strip() or "comfy_output"
105
+ zip_filename = f"{safe_prefix}_{timestamp}.zip"
106
+
107
+ tmp_dir = tempfile.gettempdir()
108
+ zip_path = os.path.join(tmp_dir, zip_filename)
109
+ zip_abs = os.path.abspath(zip_path)
110
+
111
+ # 5. Build the zip archive of everything under output/
112
+ with zipfile.ZipFile(zip_path, "w", zipfile.ZIP_DEFLATED) as zipf:
113
+ for root, _, files in os.walk(output_dir):
114
+ for fname in files:
115
+ file_path = os.path.join(root, fname)
116
+ # Just in case tempdir == output_dir, avoid zipping ourselves
117
+ if os.path.abspath(file_path) == zip_abs:
118
+ continue
119
+ rel_path = os.path.relpath(file_path, output_dir)
120
+ zipf.write(file_path, arcname=rel_path)
121
+
122
+ # 6. Prepare Hugging Face upload
123
+ repo_id = (hf_repo_id or "").strip()
124
+ if not repo_id:
125
+ # Clean up zip if we created it but can't use it
126
+ try:
127
+ os.remove(zip_path)
128
+ except OSError:
129
+ pass
130
+ raise RuntimeError("hf_repo_id cannot be empty")
131
+
132
+ remote_dir = (remote_dir or "").strip().strip("/")
133
+ if remote_dir:
134
+ path_in_repo = f"{remote_dir}/{zip_filename}"
135
+ else:
136
+ path_in_repo = zip_filename
137
+
138
+ api = HfApi()
139
+
140
+ # 7. Upload to Hugging Face
141
+ try:
142
+ api.upload_file(
143
+ path_or_fileobj=zip_path,
144
+ path_in_repo=path_in_repo,
145
+ repo_id=repo_id,
146
+ # token is optional; if empty, hf_hub will use env/CLI token if present
147
+ token=hf_token or None,
148
+ )
149
+ except Exception as e:
150
+ # Clean up local zip on failure
151
+ try:
152
+ os.remove(zip_path)
153
+ except OSError:
154
+ pass
155
+ raise RuntimeError(f"Failed to upload to Hugging Face: {e}")
156
+
157
+ # 8. Build a direct download URL
158
+ # This gives the raw file: https://huggingface.co/{repo_id}/resolve/main/{path_in_repo}
159
+ download_url = f"https://huggingface.co/{repo_id}/resolve/main/{path_in_repo}"
160
+
161
+ # 9. Clean up temp zip (we only keep the file on HF)
162
+ try:
163
+ os.remove(zip_path)
164
+ except OSError:
165
+ pass
166
+
167
+ # Return as a single STRING output
168
+ return (download_url,)
169
+
170
+
171
+ # Register node with ComfyUI
172
+ NODE_CLASS_MAPPINGS = {
173
+ "ZipOutputToHuggingFace": ZipOutputToHuggingFace,
174
+ }
175
+
176
+ NODE_DISPLAY_NAME_MAPPINGS = {
177
+ "ZipOutputToHuggingFace": "Zip Output → Hugging Face",
178
+ }