|  | @@ -1,22 +1,34 @@
 | 
	
		
			
				|  |  |  package cn.newfeifan.mall.module.infra.controller.app.file;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  import cn.hutool.core.io.IoUtil;
 | 
	
		
			
				|  |  | +import cn.hutool.core.io.resource.InputStreamResource;
 | 
	
		
			
				|  |  |  import cn.newfeifan.mall.framework.common.pojo.CommonResult;
 | 
	
		
			
				|  |  |  import cn.newfeifan.mall.module.infra.controller.app.file.vo.AppFileUploadReqVO;
 | 
	
		
			
				|  |  |  import cn.newfeifan.mall.module.infra.service.file.FileService;
 | 
	
		
			
				|  |  |  import io.swagger.v3.oas.annotations.Operation;
 | 
	
		
			
				|  |  |  import io.swagger.v3.oas.annotations.tags.Tag;
 | 
	
		
			
				|  |  |  import lombok.extern.slf4j.Slf4j;
 | 
	
		
			
				|  |  | +import org.springframework.core.io.ByteArrayResource;
 | 
	
		
			
				|  |  | +import org.springframework.http.HttpHeaders;
 | 
	
		
			
				|  |  | +import org.springframework.http.HttpStatus;
 | 
	
		
			
				|  |  | +import org.springframework.http.MediaType;
 | 
	
		
			
				|  |  | +import org.springframework.http.ResponseEntity;
 | 
	
		
			
				|  |  | +import org.springframework.util.StreamUtils;
 | 
	
		
			
				|  |  |  import org.springframework.validation.annotation.Validated;
 | 
	
		
			
				|  |  | -import org.springframework.web.bind.annotation.PostMapping;
 | 
	
		
			
				|  |  | -import org.springframework.web.bind.annotation.RequestMapping;
 | 
	
		
			
				|  |  | -import org.springframework.web.bind.annotation.RestController;
 | 
	
		
			
				|  |  | +import org.springframework.web.bind.annotation.*;
 | 
	
		
			
				|  |  | +import org.springframework.web.client.RestTemplate;
 | 
	
		
			
				|  |  |  import org.springframework.web.multipart.MultipartFile;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  import javax.annotation.Resource;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  import static cn.newfeifan.mall.framework.common.pojo.CommonResult.success;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +import java.io.ByteArrayInputStream;
 | 
	
		
			
				|  |  | +import java.io.IOException;
 | 
	
		
			
				|  |  | +import java.io.InputStream;
 | 
	
		
			
				|  |  | +import java.net.URL;
 | 
	
		
			
				|  |  | +import java.net.URLConnection;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |  @Tag(name = "用户 App - 文件存储")
 | 
	
		
			
				|  |  |  @RestController
 | 
	
		
			
				|  |  |  @RequestMapping("/infra/file")
 | 
	
	
		
			
				|  | @@ -27,6 +39,10 @@ public class AppFileController {
 | 
	
		
			
				|  |  |      @Resource
 | 
	
		
			
				|  |  |      private FileService fileService;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    @Resource
 | 
	
		
			
				|  |  | +    private RestTemplate restTemplate;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |      @PostMapping("/upload")
 | 
	
		
			
				|  |  |      @Operation(summary = "上传文件")
 | 
	
		
			
				|  |  |      public CommonResult<String> uploadFile(AppFileUploadReqVO uploadReqVO) throws Exception {
 | 
	
	
		
			
				|  | @@ -35,4 +51,41 @@ public class AppFileController {
 | 
	
		
			
				|  |  |          return success(fileService.createFile(file.getOriginalFilename(), path, IoUtil.readBytes(file.getInputStream())));
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +    @GetMapping("/downloadByUrl")
 | 
	
		
			
				|  |  | +    @Operation(summary = "通过链接下载文件流")
 | 
	
		
			
				|  |  | +    public ResponseEntity<ByteArrayResource> downloadByUrl(@RequestParam("fileUrl") String fileUrl) throws Exception {
 | 
	
		
			
				|  |  | +        try {
 | 
	
		
			
				|  |  | +            URL url = new URL(fileUrl);
 | 
	
		
			
				|  |  | +            URLConnection connection = url.openConnection();
 | 
	
		
			
				|  |  | +            byte[] data = StreamUtils.copyToByteArray(connection.getInputStream());
 | 
	
		
			
				|  |  | +            ByteArrayResource resource = new ByteArrayResource(data);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +            String[] path = fileUrl.split("/?\\?", 2)[0].split("/");  // Ignore query parameters
 | 
	
		
			
				|  |  | +            String filename = path[path.length - 1];
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +            HttpHeaders headers = new HttpHeaders();
 | 
	
		
			
				|  |  | +            headers.add(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=" + filename);
 | 
	
		
			
				|  |  | +            headers.add("Cache-Control", "no-cache, no-store, must-revalidate");
 | 
	
		
			
				|  |  | +            headers.add("Pragma", "no-cache");
 | 
	
		
			
				|  |  | +            headers.add("Expires", "0");
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +            MediaType contentType = MediaType.APPLICATION_OCTET_STREAM; // Default content type
 | 
	
		
			
				|  |  | +            try {
 | 
	
		
			
				|  |  | +                contentType = MediaType.parseMediaType(connection.getContentType());
 | 
	
		
			
				|  |  | +            } catch (IllegalArgumentException ex) {
 | 
	
		
			
				|  |  | +                // Log warning and fall back to default content type
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +            return ResponseEntity.ok()
 | 
	
		
			
				|  |  | +                    .headers(headers)
 | 
	
		
			
				|  |  | +                    .contentLength(connection.getContentLengthLong())
 | 
	
		
			
				|  |  | +                    .contentType(contentType)
 | 
	
		
			
				|  |  | +                    .body(resource);
 | 
	
		
			
				|  |  | +        } catch (IOException e) {
 | 
	
		
			
				|  |  | +            return null;
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |  }
 |