ricebug commited on
Commit
565a796
·
verified ·
1 Parent(s): 1397917

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +19 -18
app.py CHANGED
@@ -30,7 +30,7 @@ app.secret_key = os.getenv('FLASK_SECRET_KEY', os.urandom(24))
30
  APP_TOKEN = os.getenv('APP_TOKEN', 'admin123')
31
  STORAGE_MODE = os.getenv('STORAGE_MODE', 'cloud').lower()
32
 
33
- # 并发控制:默认 5 个线程
34
  MAX_WORKERS = int(os.getenv('MAX_WORKERS', 5))
35
 
36
  # 图床配置
@@ -73,7 +73,10 @@ def get_file_list_from_disk():
73
  mtime = 0
74
  time_str = "Unknown"
75
 
76
- url = f"{SITE_DOMAIN}/api/download/{filename}?t={int(mtime)}"
 
 
 
77
 
78
  files_data.append({
79
  'filename': filename,
@@ -156,6 +159,7 @@ def save_to_local(image_data, original_url, content_type, folder_name):
156
  unique_name = f"{uuid.uuid4().hex}{ext}"
157
  path = os.path.join(save_dir, unique_name)
158
  with open(path, 'wb') as f: f.write(image_data)
 
159
  return f"{SITE_DOMAIN}/{LOCAL_IMAGE_FOLDER}/{safe_folder}/{unique_name}"
160
  except Exception as e:
161
  logger.error(f"Local Save Error: {e}")
@@ -165,14 +169,11 @@ def save_to_local(image_data, original_url, content_type, folder_name):
165
  def process_single_image_task(url, filename_no_ext):
166
  """
167
  下载并上传单个图片
168
- 返回: (原始URL, 新URL) 或 (原始URL, None)
169
  """
170
- # 1. 下载
171
  img_data, c_type = download_image(url)
172
  if not img_data:
173
  return url, None
174
 
175
- # 2. 上传/保存
176
  fname = url.split('/')[-1].split('?')[0] or "image.jpg"
177
  new_url = None
178
 
@@ -189,52 +190,49 @@ def process_markdown_content(content, filename_no_ext):
189
  """
190
  pattern = re.compile(r'!\[(.*?)\]\((.*?)\)')
191
 
192
- # 1. 扫描所有图片链接
193
- matches = pattern.findall(content) # 返回 [(alt, url), (alt, url)...]
194
 
195
- # 2. 筛选出需要处理的 URL (去重,且必须是 http 开头,且不是本站域名)
196
  unique_urls = set()
197
  for _, url in matches:
198
  if url.startswith(('http://', 'https://')):
199
- # 如果是本地模式,排除掉已经是本站的链接
200
  if STORAGE_MODE == 'local' and SITE_DOMAIN in url:
201
  continue
202
  unique_urls.add(url)
203
 
204
  logger.info(f"Found {len(matches)} images, {len(unique_urls)} need processing.")
205
 
206
- # 3. 线程池并发处理
207
- url_map = {} # 旧URL -> 新URL
208
  success_count = 0
209
  failed_count = 0
210
 
211
  if unique_urls:
212
  with ThreadPoolExecutor(max_workers=MAX_WORKERS) as executor:
213
- # 提交任务
214
  future_to_url = {
215
  executor.submit(process_single_image_task, url, filename_no_ext): url
216
  for url in unique_urls
217
  }
218
 
219
- # 获取结果
220
  for future in as_completed(future_to_url):
221
  old_url, new_url = future.result()
222
  if new_url:
223
- url_map[old_url] = new_url
 
 
 
 
 
 
224
  success_count += 1
225
  else:
226
  failed_count += 1
227
 
228
- # 4. 执行替换 (使用 re.sub 和 映射表)
229
  def replace_callback(match):
230
  alt_text = match.group(1)
231
  original_url = match.group(2)
232
 
233
- # 如果在映射表中,说明处理成功,替换之
234
  if original_url in url_map:
235
  return f'![{alt_text}]({url_map[original_url]})'
236
 
237
- # 否则保持原样
238
  return match.group(0)
239
 
240
  new_content = pattern.sub(replace_callback, content)
@@ -248,7 +246,10 @@ def save_processed_md(content, original_filename):
248
  with open(save_path, 'w', encoding='utf-8') as f:
249
  f.write(content)
250
  logger.info(f"Markdown file saved: {save_path}")
251
- return f"{SITE_DOMAIN}/api/download/{safe_filename}"
 
 
 
252
 
253
  # ================= HTML 模板 (保持不变) =================
254
  BASE_TEMPLATE = """
 
30
  APP_TOKEN = os.getenv('APP_TOKEN', 'admin123')
31
  STORAGE_MODE = os.getenv('STORAGE_MODE', 'cloud').lower()
32
 
33
+ # 并发控制
34
  MAX_WORKERS = int(os.getenv('MAX_WORKERS', 5))
35
 
36
  # 图床配置
 
73
  mtime = 0
74
  time_str = "Unknown"
75
 
76
+ # URL 编码处理:文件名中可能有空格,下载链接也需要处理
77
+ # 但这里的 filename 是路径参数,通常由浏览器自动编码,这里手动替换空格更保险
78
+ encoded_filename = filename.replace(' ', '%20')
79
+ url = f"{SITE_DOMAIN}/api/download/{encoded_filename}?t={int(mtime)}"
80
 
81
  files_data.append({
82
  'filename': filename,
 
159
  unique_name = f"{uuid.uuid4().hex}{ext}"
160
  path = os.path.join(save_dir, unique_name)
161
  with open(path, 'wb') as f: f.write(image_data)
162
+ # 注意:这里返回的 URL 可能包含中文或空格
163
  return f"{SITE_DOMAIN}/{LOCAL_IMAGE_FOLDER}/{safe_folder}/{unique_name}"
164
  except Exception as e:
165
  logger.error(f"Local Save Error: {e}")
 
169
  def process_single_image_task(url, filename_no_ext):
170
  """
171
  下载并上传单个图片
 
172
  """
 
173
  img_data, c_type = download_image(url)
174
  if not img_data:
175
  return url, None
176
 
 
177
  fname = url.split('/')[-1].split('?')[0] or "image.jpg"
178
  new_url = None
179
 
 
190
  """
191
  pattern = re.compile(r'!\[(.*?)\]\((.*?)\)')
192
 
193
+ matches = pattern.findall(content)
 
194
 
 
195
  unique_urls = set()
196
  for _, url in matches:
197
  if url.startswith(('http://', 'https://')):
 
198
  if STORAGE_MODE == 'local' and SITE_DOMAIN in url:
199
  continue
200
  unique_urls.add(url)
201
 
202
  logger.info(f"Found {len(matches)} images, {len(unique_urls)} need processing.")
203
 
204
+ url_map = {}
 
205
  success_count = 0
206
  failed_count = 0
207
 
208
  if unique_urls:
209
  with ThreadPoolExecutor(max_workers=MAX_WORKERS) as executor:
 
210
  future_to_url = {
211
  executor.submit(process_single_image_task, url, filename_no_ext): url
212
  for url in unique_urls
213
  }
214
 
 
215
  for future in as_completed(future_to_url):
216
  old_url, new_url = future.result()
217
  if new_url:
218
+ # ====================================================
219
+ # 【核心修改】在这里对 URL 进行编码处理
220
+ # 将空格替换为 %20,保证 Markdown 解析正常
221
+ # ====================================================
222
+ encoded_new_url = new_url.replace(' ', '%20')
223
+
224
+ url_map[old_url] = encoded_new_url
225
  success_count += 1
226
  else:
227
  failed_count += 1
228
 
 
229
  def replace_callback(match):
230
  alt_text = match.group(1)
231
  original_url = match.group(2)
232
 
 
233
  if original_url in url_map:
234
  return f'![{alt_text}]({url_map[original_url]})'
235
 
 
236
  return match.group(0)
237
 
238
  new_content = pattern.sub(replace_callback, content)
 
246
  with open(save_path, 'w', encoding='utf-8') as f:
247
  f.write(content)
248
  logger.info(f"Markdown file saved: {save_path}")
249
+
250
+ # 返回下载链接时,文件名也进行编码,防止下载链接断裂
251
+ encoded_filename = safe_filename.replace(' ', '%20')
252
+ return f"{SITE_DOMAIN}/api/download/{encoded_filename}"
253
 
254
  # ================= HTML 模板 (保持不变) =================
255
  BASE_TEMPLATE = """