|
@@ -27,30 +27,35 @@ headers = {
|
|
|
}
|
|
|
|
|
|
|
|
|
+def clear_file_type_suffix(filename: str, filetype: str):
|
|
|
+ filename = filename.strip()
|
|
|
+ if filetype in filename:
|
|
|
+ filename = filename.replace(f".{filetype}", '')
|
|
|
+ return filename
|
|
|
+
|
|
|
+
|
|
|
class AttachmentDownloader:
|
|
|
|
|
|
def __init__(self):
|
|
|
self.dir_name = "file"
|
|
|
|
|
|
- def create_dir(self):
|
|
|
- if not os.path.exists(self.dir_name):
|
|
|
- os.makedirs(self.dir_name, mode=0o777, exist_ok=True)
|
|
|
-
|
|
|
def create_file(self, filename, filetype):
|
|
|
- self.create_dir()
|
|
|
- sign = tools.get_sha1("{}_{}".format(filename, uuid.uuid4()))
|
|
|
- file_name = "{}.{}".format(sign, filetype)
|
|
|
- return "{}/{}".format(self.dir_name, file_name)
|
|
|
+ os.makedirs(self.dir_name, mode=0o777, exist_ok=True)
|
|
|
+ file = "{filename}.{filetype}".format(
|
|
|
+ filename=tools.get_sha1("{}_{}".format(filename, uuid.uuid4())),
|
|
|
+ filetype=filetype
|
|
|
+ )
|
|
|
+ return "{}/{}".format(self.dir_name, file)
|
|
|
|
|
|
@staticmethod
|
|
|
- def clean_attachment(file_path):
|
|
|
+ def clean_attachment(filepath):
|
|
|
"""
|
|
|
删除文件
|
|
|
|
|
|
- :param str file_path: 文件路径
|
|
|
+ :param str filepath: 文件路径
|
|
|
"""
|
|
|
try:
|
|
|
- os.remove(file_path)
|
|
|
+ os.remove(filepath)
|
|
|
except FileNotFoundError:
|
|
|
pass
|
|
|
|
|
@@ -58,9 +63,9 @@ class AttachmentDownloader:
|
|
|
self.clean_attachment(file)
|
|
|
|
|
|
@staticmethod
|
|
|
- def get_mb(data):
|
|
|
+ def calculate_size(data):
|
|
|
"""
|
|
|
- 获取数据的Mb
|
|
|
+ 计算数据大小
|
|
|
|
|
|
:param int data: 准备计算大小的内容
|
|
|
:return: float
|
|
@@ -101,12 +106,11 @@ class AttachmentDownloader:
|
|
|
|
|
|
def fetch_data(self, url, proxies=None, file=None, show_error_log=False, **kwargs):
|
|
|
"""
|
|
|
- 数据下载
|
|
|
+ 下载数据
|
|
|
|
|
|
- :param str url: 下载地址
|
|
|
+ :param str url: 文件下载地址
|
|
|
+ :param proxies: 代理 {"http":"http://xxx", "https":"https://xxx"}
|
|
|
:param file: 本地文件
|
|
|
- :param dict kwargs: requests请求参数
|
|
|
- :param dict proxies: 代理ip
|
|
|
:param show_error_log: 展示错误堆栈信息日志
|
|
|
"""
|
|
|
method = kwargs.pop("method", "get")
|
|
@@ -127,12 +131,11 @@ class AttachmentDownloader:
|
|
|
with requests.request(method, url, **request_kwargs) as req:
|
|
|
stream = io.BytesIO()
|
|
|
lh = {k.lower(): v for k, v in req.headers.items()}
|
|
|
- '''内容长度'''
|
|
|
- cl = lh.get("content-length") or len(req.content)
|
|
|
+ cl = lh.get("content-length") or len(req.content) # 内容长度
|
|
|
icl = int(cl)
|
|
|
- content_length = self.get_mb(icl)
|
|
|
+ content_length = self.calculate_size(icl)
|
|
|
if content_length > 50:
|
|
|
- '''丢弃超过50Mb内容长度的文件'''
|
|
|
+ # 丢弃超过50Mb内容长度的文件
|
|
|
return stream.getvalue()
|
|
|
|
|
|
if req.status_code != 200:
|
|
@@ -168,11 +171,11 @@ class AttachmentDownloader:
|
|
|
|
|
|
def _push_oss_from_stream(self, filename, filetype, url, **kwargs):
|
|
|
"""
|
|
|
- 将数据流推送oss
|
|
|
+ 推送数据流到oss
|
|
|
|
|
|
:param str filename: 文件名称
|
|
|
:param str filetype: 文件类型
|
|
|
- :param str url: 下载地址
|
|
|
+ :param str url: 文件下载地址
|
|
|
"""
|
|
|
stream = self.fetch_data(url, file=None, **kwargs)
|
|
|
attachment = {
|
|
@@ -187,18 +190,20 @@ class AttachmentDownloader:
|
|
|
attachment["size"] = self.getsize(stream)
|
|
|
attachment["url"] = "oss"
|
|
|
AliYunService().push_oss_from_stream(attachment["fid"], stream)
|
|
|
- except Exception:
|
|
|
- pass
|
|
|
+ except Exception as e:
|
|
|
+ logger.error(
|
|
|
+ "[{}]上传失败,原因:{}".format(filename, e.__class__.__name__)
|
|
|
+ )
|
|
|
|
|
|
return attachment
|
|
|
|
|
|
def _push_oss_from_local(self, filename, filetype, url, **kwargs):
|
|
|
"""
|
|
|
- 将本地文件推送oss
|
|
|
+ 上传本地文件到oss
|
|
|
|
|
|
:param str filename: 文件名称
|
|
|
:param str filetype: 文件类型
|
|
|
- :param str url: 下载地址
|
|
|
+ :param str url: 文件下载地址
|
|
|
"""
|
|
|
file = self.create_file(filename, filetype)
|
|
|
stream = self.fetch_data(url, file=file, **kwargs)
|
|
@@ -223,38 +228,38 @@ class AttachmentDownloader:
|
|
|
self.remove(file) # 删除本地临时文件
|
|
|
return attachment
|
|
|
|
|
|
- def _fetch_attachment(self, filename, filetype, download_url, mode, **kwargs):
|
|
|
- """
|
|
|
- 下载附件
|
|
|
-
|
|
|
- :param str filename: 文件名称
|
|
|
- :param str filetype: 文件类型
|
|
|
- :param str download_url: 下载地址
|
|
|
- :param str mode: 附件上传模式 "local" or "stream"
|
|
|
- """
|
|
|
- file_kwargs = dict(
|
|
|
- filename=filename,
|
|
|
- filetype=filetype,
|
|
|
- url=download_url,
|
|
|
- **kwargs
|
|
|
- )
|
|
|
- if mode == "stream":
|
|
|
- res = self._push_oss_from_stream(**file_kwargs)
|
|
|
- else:
|
|
|
- res = self._push_oss_from_local(**file_kwargs)
|
|
|
- return res
|
|
|
-
|
|
|
def fetch_attachment(
|
|
|
self,
|
|
|
file_name: str,
|
|
|
file_type: str,
|
|
|
download_url: str,
|
|
|
- proxies=None,
|
|
|
mode="local",
|
|
|
+ proxies=None,
|
|
|
**kwargs
|
|
|
):
|
|
|
+ """
|
|
|
+ 下载附件
|
|
|
+
|
|
|
+ @param file_name: 文件名称
|
|
|
+ @param file_type: 文件类型
|
|
|
+ @param download_url: 文件下载地址
|
|
|
+ @param mode: 附件上传模式 "local" = 本地文件 or "stream" = 数据流
|
|
|
+ @param proxies: 代理 {"http":"http://xxx", "https":"https://xxx"}
|
|
|
+ @return:
|
|
|
+ """
|
|
|
if not file_name or not file_type or not download_url:
|
|
|
raise AttachmentNullError
|
|
|
|
|
|
- file_kwargs = dict(proxies=proxies, **kwargs)
|
|
|
- return self._fetch_attachment(file_name, file_type, download_url, mode, **file_kwargs)
|
|
|
+ file_name = clear_file_type_suffix(file_name, file_type) # 防止文件后缀重复
|
|
|
+ file_kwargs = dict(
|
|
|
+ filename=file_name,
|
|
|
+ filetype=file_type,
|
|
|
+ url=download_url,
|
|
|
+ proxies=proxies,
|
|
|
+ **kwargs
|
|
|
+ )
|
|
|
+ if mode == "stream":
|
|
|
+ attachment = self._push_oss_from_stream(**file_kwargs)
|
|
|
+ else:
|
|
|
+ attachment = self._push_oss_from_local(**file_kwargs)
|
|
|
+ return attachment
|