i0110 commited on
Commit
2ea3a9e
·
verified ·
1 Parent(s): 470e738

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +65 -67
app.py CHANGED
@@ -1,83 +1,81 @@
1
- from flask import Flask, render_template, request, send_file
 
 
2
  import requests
 
 
3
  import zipfile
4
- from io import BytesIO
5
- from urllib.parse import urlparse
6
 
7
- # 创建 Flask 应用实例
8
  app = Flask(__name__)
 
9
 
10
- def is_directory(url):
11
- """检查 URL 是否指向 GitHub 文件夹"""
12
- pathname = urlparse(url).path.split("/")
13
- return "tree" in pathname and len(pathname) > 5
 
 
 
 
 
14
 
15
- def get_repo_info_from_url(url):
16
- """从 GitHub URL 中提取仓库信息"""
17
- pathname = urlparse(url).path.split("/")
18
- owner = pathname[1]
19
- repo = pathname[2]
20
- branch = pathname[4]
21
- folder_path = "/".join(pathname[5:])
22
- return owner, repo, branch, folder_path
 
 
 
23
 
24
- def fetch_folder_contents(owner, repo, branch, folder_path):
25
- """获取文件夹内容"""
26
- api_url = f"https://api.github.com/repos/{owner}/{repo}/contents/{folder_path}?ref={branch}"
27
- response = requests.get(api_url)
28
- if response.status_code != 200:
29
- raise Exception(f"Unable to fetch folder contents: {response.status_code}")
30
- return response.json()
 
31
 
32
- def download_file(file_url):
33
- """下载单个文件"""
34
- response = requests.get(file_url)
35
- if response.status_code != 200:
36
- raise Exception(f"Unable to download file: {response.status_code}")
37
- return response.content
38
 
39
- def create_zip(files):
40
- """将文件打包成 ZIP"""
41
- zip_buffer = BytesIO()
42
- with zipfile.ZipFile(zip_buffer, "a", zipfile.ZIP_DEFLATED, False) as zip_file:
43
- for file_name, file_content in files.items():
44
- zip_file.writestr(file_name, file_content)
45
- zip_buffer.seek(0)
46
- return zip_buffer
 
 
47
 
48
- @app.route("/", methods=["GET", "POST"])
49
- def index():
50
- if request.method == "POST":
51
- github_url = request.form["github_url"]
52
-
53
- if not is_directory(github_url):
54
- return "Error: Please provide a valid GitHub folder URL."
55
 
56
- try:
57
- # 提取仓库信息
58
- owner, repo, branch, folder_path = get_repo_info_from_url(github_url)
 
 
 
 
59
 
60
- # 获取文件夹内容
61
- contents = fetch_folder_contents(owner, repo, branch, folder_path)
 
 
62
 
63
- # 下载所有文件
64
- files = {}
65
- for item in contents:
66
- if item["type"] == "file":
67
- file_content = download_file(item["download_url"])
68
- files[item["name"]] = file_content
69
 
70
- # 打包成 ZIP
71
- zip_buffer = create_zip(files)
72
- return send_file(
73
- zip_buffer,
74
- download_name=f"{repo}_{folder_path.replace('/', '_')}.zip",
75
- as_attachment=True,
76
- )
77
- except Exception as e:
78
- return f"Error: {str(e)}"
79
 
80
- return render_template("index.html")
81
 
82
- if __name__ == "__main__":
83
- app.run(host="0.0.0.0", port=5000)
 
1
+ import os
2
+ import tempfile
3
+ from flask import Flask, render_template, request, send_file, flash
4
  import requests
5
+ from git import Repo
6
+ import shutil
7
  import zipfile
8
+ import re
 
9
 
 
10
  app = Flask(__name__)
11
+ app.secret_key = 'your_secret_key' # 更改为更安全的密钥
12
 
13
+ def download_github_files(repo_url, file_paths):
14
+ """GitHub仓库下载指定路径的文件,并打包成zip。"""
15
+ try:
16
+ temp_dir = tempfile.mkdtemp()
17
+ repo_name = repo_url.split('/')[-1].replace(".git", "")
18
+ local_repo_path = os.path.join(temp_dir, repo_name)
19
+
20
+ # 克隆仓库
21
+ Repo.clone_from(repo_url, local_repo_path)
22
 
23
+ zip_file_path = os.path.join(temp_dir, f"{repo_name}_files.zip")
24
+ with zipfile.ZipFile(zip_file_path, 'w', zipfile.ZIP_DEFLATED) as zf:
25
+ for file_path in file_paths:
26
+ abs_file_path = os.path.join(local_repo_path, file_path)
27
+ if os.path.exists(abs_file_path) and os.path.isfile(abs_file_path):
28
+ zf.write(abs_file_path, os.path.basename(abs_file_path))
29
+ elif os.path.exists(abs_file_path) and os.path.isdir(abs_file_path):
30
+ for root, dirs, files in os.walk(abs_file_path):
31
+ for file in files:
32
+ file_abs_path = os.path.join(root, file)
33
+ zf.write(file_abs_path, os.path.relpath(file_abs_path, local_repo_path))
34
 
35
+ shutil.rmtree(local_repo_path) # 删除克隆的仓库
36
+ if os.path.exists(zip_file_path) and os.path.getsize(zip_file_path) > 0:
37
+ return zip_file_path, f"{repo_name}_files.zip"
38
+ else:
39
+ return None, None
40
+ except Exception as e:
41
+ print(f"Error during download: {e}")
42
+ return None, None
43
 
 
 
 
 
 
 
44
 
45
+ def parse_github_url(url):
46
+ """解析 GitHub URL,提取仓库 URL 和文件路径。"""
47
+ match = re.match(r'https://github\.com/([^/]+)/([^/]+)/tree/([^/]+)(.*)', url)
48
+ if match:
49
+ owner, repo, branch, path = match.groups()
50
+ repo_url = f'https://github.com/{owner}/{repo}.git'
51
+ file_paths = [path.lstrip('/')] if path else []
52
+ return repo_url, file_paths
53
+ else:
54
+ return None, None
55
 
 
 
 
 
 
 
 
56
 
57
+ @app.route('/', methods=['GET', 'POST'])
58
+ def index():
59
+ if request.method == 'POST':
60
+ repo_path = request.form.get('repo_path')
61
+ if not repo_path:
62
+ flash('请提供 GitHub 链接', 'error')
63
+ return render_template('index.html')
64
 
65
+ repo_url, file_paths = parse_github_url(repo_path)
66
+ if not repo_url:
67
+ flash('无效的 GitHub 链接', 'error')
68
+ return render_template('index.html')
69
 
70
+ zip_path, zip_filename = download_github_files(repo_url, file_paths)
71
+ if zip_path:
72
+ return send_file(zip_path, as_attachment=True, download_name=zip_filename)
73
+ else:
74
+ flash('下载失败,请检查链接和文件路径。', 'error')
75
+ return render_template('index.html')
76
 
77
+ return render_template('index.html')
 
 
 
 
 
 
 
 
78
 
 
79
 
80
+ if __name__ == '__main__':
81
+ app.run(debug=True, host="0.0.0.0")