SpringSunYY 5 месяцев назад
Родитель
Сommit
45fb4448d7
2 измененных файлов с 68 добавлено и 29 удалено
  1. 54 23
      ruoyi_admin/controller/common/common.py
  2. 14 6
      ruoyi_common/utils/base.py

+ 54 - 23
ruoyi_admin/controller/common/common.py

@@ -12,8 +12,8 @@ from werkzeug.exceptions import NotFound
 from ruoyi_common.config import RuoYiConfig
 from ruoyi_common.constant import Constants
 from ruoyi_common.descriptor.serializer import JsonSerializer
-from ruoyi_common.descriptor.validator import FileValidator, QueryValidator
-from ruoyi_common.base.model import AjaxResponse, MultiFile
+from ruoyi_common.descriptor.validator import FileUploadValidator, QueryValidator
+from ruoyi_common.base.model import AjaxResponse
 from ruoyi_common.utils import FileUploadUtil, FileUtil, StringUtil
 from ... import reg
 
@@ -25,11 +25,11 @@ def common_download(
     file_name:Annotated[str,Field(min_length=1,max_length=100)],
     delete:Annotated[bool,Field(annotations=bool,default=False)],
 ):
-    file_path = RuoYiConfig.download_path + file_name
+    file_path = RuoYiConfig().download_path + file_name
     download_name = time.time() * 1000 + file_name[file_name.index("_") + 1:]
     try:
         response = send_from_directory(
-            directory=RuoYiConfig.download_path,
+            directory=RuoYiConfig().download_path,
             path=file_name,
             as_attachment=True,
             download_name=download_name,
@@ -43,33 +43,63 @@ def common_download(
     return response
 
 
-@reg.api.route('/common/upload')
-@FileValidator()
+@reg.api.route('/profile/<path:resource>')
 @JsonSerializer()
-def common_upload(file:MultiFile):
-    file:FileStorage = file.one()
-    file_name = FileUploadUtil.upload(file,RuoYiConfig.upload_path)
+def profile_resource(resource:str):
+    """
+    通过 /profile/** 访问上传资源
+    例如:/profile/uploads/dev/upload/2025/11/11/xxx.jpg
+    """
+    # 安全处理相对路径
+    safe_path = resource.replace("..", "").lstrip("/\\")
+    try:
+        directory = os.path.dirname(safe_path) or "."
+        filename = os.path.basename(safe_path)
+        response = send_from_directory(
+            directory=directory,
+            path=filename,
+            as_attachment=False,
+            download_name=filename,
+        )
+    except NotFound:
+        return AjaxResponse.from_error("文件不存在")
+    except Exception:
+        return AjaxResponse.from_error("读取文件失败")
+    return response
+
+
+@reg.api.route('/common/upload', methods=['POST'])
+@FileUploadValidator()
+@JsonSerializer()
+def common_upload():
+    file:FileStorage = request.files.get('file')
+    if not file:
+        return AjaxResponse.from_error("上传文件不能为空")
+    file_name = FileUploadUtil.upload(file, RuoYiConfig().upload_path)
     url = request.host_url[:-1] + file_name
     new_file_name = FileUploadUtil.get_filename(file_name)
     original_filename = file.filename
     ajax_response = AjaxResponse.from_success()
+    # 兼容前端组件字段(期待 fileName)
     setattr(ajax_response,"url",url)
-    setattr(ajax_response,"file_name",file_name)
-    setattr(ajax_response,"new_file_name",new_file_name)
-    setattr(ajax_response,"original_filename",original_filename)
+    setattr(ajax_response,"fileName",file_name)
+    setattr(ajax_response,"newFileName",new_file_name)
+    setattr(ajax_response,"originalFilename",original_filename)
     return ajax_response
 
 
-@reg.api.route('/common/uploads')
-@FileValidator()
+@reg.api.route('/common/uploads', methods=['POST'])
+@FileUploadValidator()
 @JsonSerializer()
-def common_uploads(files:MultiFile):
+def common_uploads():
     file_names = []
     urls = []
     new_file_names = []
     original_filenames = []
-    for _,file in files.items():
-        file_name = FileUploadUtil.upload(file,RuoYiConfig.upload_path)
+    if not request.files:
+        return AjaxResponse.from_error("上传文件不能为空")
+    for _,file in request.files.items():
+        file_name = FileUploadUtil.upload(file, RuoYiConfig().upload_path)
         file_names.append(file_name)
         url = request.host_url[:-1] + file_name
         urls.append(url)
@@ -78,10 +108,11 @@ def common_uploads(files:MultiFile):
         original_filename = file.filename
         original_filenames.append(original_filename)
     ajax_response = AjaxResponse.from_success()
-    setattr(ajax_response,"urls",urls.join(","))
-    setattr(ajax_response,"file_names",file_names.join(","))
-    setattr(ajax_response,"new_file_names",new_file_names.join(","))
-    setattr(ajax_response,"original_filenames",original_filenames.join(","))
+    # 兼容 camelCase
+    setattr(ajax_response,"urls", ",".join(urls))
+    setattr(ajax_response,"fileNames", ",".join(file_names))
+    setattr(ajax_response,"newFileNames", ",".join(new_file_names))
+    setattr(ajax_response,"originalFilenames", ",".join(original_filenames))
     return ajax_response
 
 
@@ -91,11 +122,11 @@ def common_uploads(files:MultiFile):
 def common_download_resource(
     resource:Annotated[str,Field(annotation=str,min_length=1,max_length=100)]
 ):
-    download_path = RuoYiConfig.download_path + StringUtil.substring_after(resource,Constants.RESOURCE_PREFIX)
+    download_path = RuoYiConfig().download_path + StringUtil.substring_after(resource,Constants.RESOURCE_PREFIX)
     download_name = os.path.basename(download_path)
     try:
         response = send_from_directory(
-            directory=RuoYiConfig.download_path,
+            directory=RuoYiConfig().download_path,
             path=download_path,
             as_attachment=True,
             download_name=download_name,

+ 14 - 6
ruoyi_common/utils/base.py

@@ -612,6 +612,7 @@ class MimeTypeUtil:
         # pdf
         "pdf" ]
     
+    @classmethod
     def get_extension(cls, mime_type:str):
         '''
         根据mime_type获取文件扩展名
@@ -768,11 +769,18 @@ class FileUploadUtil:
         Returns:
             str: 文件名
         '''
-        "{}/{}_{}.{}".format(
-            DateUtil.get_date_path(),
-            os.path.basename(file.filename),
-            Seq.get_seq_id(cls.upload_seq_type),
-            cls.get_extension(file)
+        date_path = DateUtil.get_date_path()
+        base_name = os.path.basename(file.filename)
+        seq = Seq.get_seq_id(Seq.upload_seq_type)
+        ext = cls.get_extension(file)
+        if ext and not ext.startswith("."):
+            # 统一补上点
+            ext = f".{ext}"
+        return "{}/{}_{}{}".format(
+            date_path,
+            base_name,
+            seq,
+            ext
         )
 
     @classmethod
@@ -896,7 +904,7 @@ class Seq:
         seq = str(ato.increment())
         if ato.get() > math.pow(10, length):
             ato.set(1)
-        return StringUtil.left_pad(seq, length)
+        return StringUtil.pad_left(seq, length)
         
 
 class MessageUtil: