upload_pic.py 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483
  1. from ..generate_goods_no_detail_pic.data import DataModeUploadPic
  2. import os
  3. import threading
  4. import time
  5. import concurrent.futures
  6. import re
  7. from PIL import Image
  8. from io import BytesIO
  9. from middleware import UnicornException
  10. # 详情图上传
  11. class UploadPic():
  12. # signal_data = Signal(dict)
  13. # run_end_sign = Signal(dict)
  14. # show_progress_detail_sign = Signal(str)
  15. def __init__(self, windows, to_deal_dir, config_data,token):
  16. super().__init__()
  17. self.windows = windows
  18. self.data_mode_upload_pic = DataModeUploadPic(token)
  19. self.goods_no_data = {}
  20. # ------------------
  21. # 0未选择文件,1已选文件未开始,2进行中
  22. self.state = 0
  23. self.state_change(self.state)
  24. self.to_deal_dir = to_deal_dir
  25. self.config_data = config_data
  26. def check_path(self, _path):
  27. if not os.path.exists(_path):
  28. os.mkdir(_path)
  29. return True
  30. def run_by_thread(self):
  31. self.run_by_thread_real()
  32. self.config_data["sign_text"] = "结束"
  33. self.run_end_sign.emit(self.config_data)
  34. def run(self):
  35. self.run_by_thread_real()
  36. def run_by_thread_real(self, *args):
  37. self.show_info("====开始处理====")
  38. # 统计哪些需要处理
  39. total_num = 0
  40. flag = True
  41. # group_folders 分组文件夹
  42. for group_folders in os.listdir(self.to_deal_dir):
  43. path = "{}\{}".format(self.to_deal_dir, group_folders)
  44. if not os.path.isdir(path):
  45. continue
  46. for goods_no in os.listdir(path):
  47. # 检测是不是货号或款号文件夹
  48. goods_no_path = "{}\{}\{}".format(self.to_deal_dir, group_folders, goods_no)
  49. if not os.path.isdir(goods_no_path):
  50. continue
  51. total_num += 1
  52. # 检查每个款号文件夹是不是合规
  53. # 款的一级目录文件
  54. files = os.listdir(goods_no_path)
  55. if "details" not in files:
  56. continue
  57. not_goods_art_msg = ""
  58. for f in files:
  59. f_path = "{}\{}\{}\{}".format(self.to_deal_dir, group_folders, goods_no, f)
  60. if os.path.isdir(f_path):
  61. # 处理货号文件夹
  62. if "details" != f and "货号素材" not in f and "main" not in f and "拼接图" not in f:
  63. # 是否货号文件夹判断
  64. if not self.is_goods_art_dir(f, goods_no):
  65. self.show_info("{}文件夹下 {} {} 疑似不是货号".format(group_folders, goods_no, f))
  66. not_goods_art_msg += (
  67. "{}文件夹下 {} {} 疑似不是货号".format(
  68. group_folders, goods_no, f
  69. )
  70. + "\n"
  71. )
  72. flag = False
  73. if not flag:
  74. self.show_info("请解决以上问题后重试")
  75. raise UnicornException(f"请解决:\n{not_goods_art_msg}\n以上问题后重试")
  76. return
  77. if total_num == 0:
  78. self.show_info("没有任何款号文件夹 需要上传")
  79. raise UnicornException("没有任何款号文件夹 需要上传")
  80. return
  81. self.lock = threading.Lock()
  82. error_data = []
  83. n = 0
  84. for group_folders in os.listdir(self.to_deal_dir):
  85. path = "{}\{}".format(self.to_deal_dir, group_folders)
  86. if not os.path.isdir(path):
  87. continue
  88. for goods_no in os.listdir(path):
  89. goods_no_path = "{}\{}\{}".format(self.to_deal_dir, group_folders, goods_no)
  90. if not os.path.isdir(goods_no_path):
  91. self.show_info("{} 不是文件夹".format(goods_no))
  92. continue
  93. if goods_no in self.data_mode_upload_pic.is_deal_goods_no:
  94. continue
  95. else:
  96. self.data_mode_upload_pic.is_deal_goods_no.append(goods_no)
  97. # ================处理单个款号信息,图片上传处理============
  98. self.show_info("开始处理 {}".format(goods_no))
  99. # try:
  100. if self.deal_goods_pic(goods_no, goods_no_path):
  101. # 移动文件到已完成
  102. # dest = "{}\{}\{}".format(self.is_deal_dir, group_folders, goods_no)
  103. # if os.path.exists(dest):
  104. # self.show_info("{} 文件夹在目标目录已存在".format(goods_no))
  105. # else:
  106. # shutil.move(goods_no_path, dest)
  107. self.show_info("{} 上传成功".format(goods_no))
  108. else:
  109. self.show_info("{} 处理失败".format(goods_no))
  110. error_data.append(goods_no)
  111. pass
  112. # except BaseException as e:
  113. # self.show_info("上传异常:{},{}".format(goods_no, e))
  114. # raise UnicornException("上传异常:{},{}".format(goods_no, e))
  115. # n += 1
  116. # self.show_info({"type": "show_p",
  117. # "data": int(n * 100 / total_num)})
  118. self.show_info("========已结束========== ")
  119. if error_data:
  120. self.show_info("以下编号/款号处理失败")
  121. error_msg = ""
  122. for data in error_data:
  123. self.show_info("{}".format(data))
  124. error_msg += data+"\n"
  125. raise UnicornException(f"以下编号/款号处理失败\n{error_msg}")
  126. # self.show_info({"type": "change_state",
  127. # "data": 2})
  128. def deal_goods_pic(self, goods_no, goods_no_path):
  129. """
  130. 两种模式:货号模式、编号模式
  131. :param goods_no:
  132. :param goods_no_path:
  133. :return:
  134. """
  135. print("==========开始上传系统=============")
  136. s = time.time()
  137. self.show_info("{} 开始上传 ".format(goods_no))
  138. if "NUM" in goods_no.upper():
  139. mode = "编号"
  140. else:
  141. mode = "货号"
  142. # 校验所有编号是否存在,是否是同个款
  143. _numbers = []
  144. if mode == "编号":
  145. _numbers.append(goods_no)
  146. self.goods_no_data[goods_no] = {}
  147. # 收集该款号下可能存在的货号或编号
  148. files = os.listdir(goods_no_path)
  149. if "details" not in files:
  150. self.show_info("{} 缺少details 文件夹".format(goods_no, ))
  151. raise UnicornException("{} 缺少details 文件夹".format(goods_no))
  152. return False
  153. for f in files:
  154. f_path = "{}\{}".format(goods_no_path, f)
  155. if os.path.isdir(f_path):
  156. if "details" != f and "货号素材" not in f and "main" not in f and "拼接图" not in f:
  157. if not self.is_goods_art_dir(f, goods_no):
  158. self.show_info("{} {} 疑似不是货号".format(goods_no, f))
  159. # return False
  160. continue
  161. else:
  162. _numbers.append(f)
  163. if "货号素材" in f:
  164. if "_" not in f:
  165. self.show_info("{} 货号素材文件夹 格式错误".format(goods_no))
  166. raise UnicornException("{} 货号素材文件夹 格式错误".format(goods_no))
  167. return False
  168. # 校验所有编号是否存在,是否是同个款
  169. if mode == "编号":
  170. _numbers = [x.replace("KNUM", "").replace("NUM", "") for x in _numbers]
  171. _numbers = list(set(_numbers))
  172. goods_number_data = self.data_mode_upload_pic.get_goods_art_no_info(numbers_list=_numbers)
  173. else:
  174. if len(_numbers) == 0:
  175. _numbers = self.config_data["goods_art_nos"]
  176. goods_number_data = self.data_mode_upload_pic.get_goods_art_no_info(goods_art_list=_numbers)
  177. t = True
  178. for num in _numbers:
  179. if num not in goods_number_data:
  180. t = False
  181. if mode == "编号":
  182. self.show_info("{} 编号在系统中不存在".format(num))
  183. else:
  184. self.show_info("{} 货号在系统中不存在".format(num))
  185. else:
  186. if self.config_data["upload_is_pass"]:
  187. if self.data_mode_upload_pic.check_is_uploaded(num):
  188. t = False
  189. self.show_info("{} 货号在系统已有详情页,已跳过".format(num))
  190. return True
  191. if not t:
  192. return False
  193. print("goods_number_data", goods_number_data)
  194. _ = set([goods_number_data[x]["款号"] for x in goods_number_data])
  195. if len(_) != 1:
  196. self.show_info("{} 存在多个不同的款号".format(_))
  197. raise UnicornException("{} 存在多个不同的款号".format(_))
  198. return False
  199. # 重新定义款号
  200. goods_no = _.pop()
  201. # 上传所有图片
  202. self.pic_data = {}
  203. ignore_text = ["main", "拼接图", "货号素材"]
  204. _Type = [
  205. ".png",
  206. ".PNG",
  207. ".jpg",
  208. ".JPG",
  209. ".gif",
  210. ".GIF",
  211. ".webp",
  212. ".WEBP",
  213. ".AVIF",
  214. ".avif",
  215. ]
  216. for dirpath, dirnames, filenames in os.walk(goods_no_path):
  217. for file in filenames:
  218. if os.path.splitext(file)[1] in _Type:
  219. # 获取当前路径的文件夹名称
  220. f_path = dirpath + '/' + file
  221. f = True
  222. for i in ignore_text:
  223. if i in f_path:
  224. f = False
  225. break
  226. if f:
  227. print(f_path)
  228. f_path = f_path.replace("\\", "/")
  229. self.pic_data[f_path] = {"url": ""}
  230. print("上传完成......................!!!!!!!!!!!!!!!!!!!")
  231. # with concurrent.futures.ThreadPoolExecutor(max_workers=10) as executor:
  232. for key in self.pic_data:
  233. if "货号素材" in key:
  234. # 货号素材图不上传
  235. is_resize = False
  236. continue
  237. else:
  238. is_resize = True
  239. # executor.submit(self.to_upload_pic, file_path=key, is_resize=is_resize)
  240. self.to_upload_pic(file_path=key, is_resize=is_resize)
  241. for key in self.pic_data:
  242. if "货号素材" in key:
  243. is_resize = False
  244. continue
  245. if not self.pic_data[key]["url"]:
  246. self.show_info("{} {} 图片未上传完成".format(key, goods_no))
  247. raise UnicornException("{} {} 图片未上传完成".format(key, goods_no))
  248. up_data = {"goods_art_no": [],
  249. "details": [],
  250. "goods_no": [],
  251. "goods_art_no_material": []
  252. }
  253. details_index = 0
  254. goods_no_index = 0
  255. # 款号转换
  256. # files 为当前款下的所有文件或文件夹
  257. for f in files:
  258. f_path = "{}\{}".format(goods_no_path, f)
  259. f_path = f_path.replace("\\", "/")
  260. # 如果为文件夹则
  261. if os.path.isdir(f_path):
  262. if "details" == f:
  263. # 处理详情图
  264. for pic in os.listdir(f_path):
  265. pic_path = "{}\{}".format(f_path, pic)
  266. pic_path = pic_path.replace("\\", "/")
  267. details_index += 1
  268. data = {
  269. "index": details_index,
  270. "name": goods_no,
  271. "number": goods_no,
  272. "status": "success",
  273. "type": "2", # 2 为详情图
  274. "uid": "",
  275. "url": self.pic_data[pic_path]["url"],
  276. }
  277. up_data["details"].append(data)
  278. pass
  279. elif "货号素材" in f:
  280. continue
  281. x = f.split("_")[0]
  282. if mode == "编号":
  283. x = f.replace("NUM", "")
  284. x = x.replace("_货号素材", "")
  285. goods_art_no = goods_number_data[x]["商品货号"]
  286. else:
  287. goods_art_no = x
  288. n = 0
  289. for pic in os.listdir(f_path):
  290. pic_path = "{}\{}".format(f_path, pic)
  291. pic_path = pic_path.replace("\\", "/")
  292. n += 1
  293. data = {
  294. "index": n,
  295. "name": goods_art_no,
  296. "number": goods_art_no,
  297. "status": "success",
  298. "type": "3",
  299. "uid": "",
  300. "url": self.pic_data[pic_path]["url"],
  301. }
  302. up_data["goods_art_no_material"].append(data)
  303. else:
  304. if "拼接图" in f:
  305. continue
  306. if "main" in f:
  307. continue
  308. # 处理货号图
  309. if mode == "编号":
  310. x = f.replace("NUM", "")
  311. goods_art_no = goods_number_data[x]["商品货号"]
  312. else:
  313. goods_art_no = f
  314. for pic in os.listdir(f_path):
  315. pic_path = "{}\{}".format(f_path, pic)
  316. pic_path = pic_path.replace("\\", "/")
  317. data = {
  318. "index": 1,
  319. "name": goods_art_no,
  320. "number": goods_art_no,
  321. "status": "success",
  322. "type": "0", # 0为货号图
  323. "uid": "",
  324. "url": self.pic_data[pic_path]["url"],
  325. }
  326. up_data["goods_art_no"].append(data)
  327. break
  328. else:
  329. # 处理款号图
  330. goods_no_index += 1
  331. data = {
  332. "index": goods_no_index,
  333. "name": goods_no,
  334. "number": goods_no,
  335. "status": "success",
  336. "type": "1",
  337. "uid": "",
  338. "url": self.pic_data[f_path]["url"],
  339. }
  340. up_data["goods_no"].append(data)
  341. pass
  342. # -----------上传数据-----------------
  343. # print(up_data["goods_no"])
  344. # print(up_data["goods_art_no_material"])
  345. # print(up_data["details"])
  346. # 上传图片
  347. for key, value in up_data.items():
  348. if value:
  349. if not self.data_mode_upload_pic.upload_pic_list_data(data={"images": value}):
  350. self.show_info("{} {}上传错误".format(goods_no, key))
  351. raise UnicornException("{} {}上传错误".format(goods_no, key))
  352. return False
  353. print("---{} {} 完成".format(goods_no, time.time() - s))
  354. return True
  355. def to_upload_pic(self, file_path, is_resize=True):
  356. file_name = os.path.split(file_path)[1]
  357. e = os.path.splitext(file_name)[1][1:]
  358. im = Picture(file_path)
  359. if im.x > 1200:
  360. im.resize(width=1200)
  361. # print(file_name, e)
  362. # if e == "png":
  363. # im.im.show()
  364. # return
  365. _ = {"jpg": "JPEG",
  366. "JPG": "JPEG",
  367. "JPEG": "JPEG",
  368. "jpeg": "JPEG",
  369. "png": "PNG",
  370. "PNG": "PNG", }
  371. e = _[e]
  372. image_io = im.save_to_io(e)
  373. # if is_resize:
  374. # im = Picture(file_path)
  375. # if im.x > 1200:
  376. # im.resize(width=1200)
  377. # image_io = im.save_to_io()
  378. # e = "JPEG"
  379. # else:
  380. # file_name = os.path.split(file_path)[1]
  381. # e = os.path.splitext(file_name)[0][1:]
  382. # image_io = open(file_path, 'rb')
  383. # image_io = open(file_path, 'rb')
  384. # self.lock.acquire()
  385. # self.pic_data[file_path]["url"] = "1111"
  386. # self.lock.release()
  387. # return
  388. goods_data = {"file_path": os.path.split(file_path)[1],
  389. "image_io": image_io,
  390. "e": e
  391. }
  392. url = self.data_mode_upload_pic.upload_pic(goods_data=goods_data)
  393. self.lock.acquire()
  394. self.pic_data[file_path]["url"] = url
  395. self.lock.release()
  396. def is_goods_art_dir(self, file, goods_no):
  397. if goods_no in file:
  398. return True
  399. # 判断是不是货号文件夹
  400. _r_text = re.findall("[a-zA-Z0-9]+", file)
  401. if _r_text:
  402. # print(_r_text)
  403. if _r_text[0] != file:
  404. # 文件夹中包含有非字母或数字判断不是货号
  405. return False
  406. else:
  407. return True
  408. else:
  409. # 非字母和数字 判断为非货号
  410. return False
  411. def show_info(self, text: str):
  412. # self.show_progress_detail_sign.emit(text)
  413. # self.windows.show_progress_detail(text)
  414. print("upload_pic=====>", text)
  415. def show_text_browser(self, text):
  416. pass
  417. def state_change(self, to_state: int):
  418. self.state = to_state
  419. class Picture:
  420. def __init__(self, in_path):
  421. self.im = Image.open(in_path)
  422. self.x, self.y = self.im.size
  423. # print(self.x, self.y)
  424. def resize(self, width):
  425. re_x = int(width)
  426. re_y = int(self.y * re_x / self.x)
  427. self.im = self.im.resize((re_x, re_y), Image.Resampling.LANCZOS)
  428. self.x, self.y = self.im.size
  429. def save_to_io(self, format):
  430. img = BytesIO()
  431. self.im.save(img, format=format) # format: PNG or JPEG
  432. img.seek(0) # rewind to the start
  433. return img