# Absolute Upload URL Implementation Plan > **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking. **Goal:** Return an environment-configured absolute file URL from the common upload endpoint so deployed case-material links do not depend on frontend proxy routing. **Architecture:** `CommonUploadController` already receives the relative path from `IFileUtil`. It will combine that path with the existing `file.url` configuration after removing a trailing slash from the configured public base. This preserves local storage and all existing upload mechanics. **Tech Stack:** Spring Boot 2.7, JUnit 5, Spring Test mock multipart files. ## Global Constraints - Use the existing `file.url` property as the public file base; do not hard-code a server host. - Preserve the empty-file response contract and existing stored relative URLs. - Build only the backend behavior needed for upload responses. --- ### Task 1: Return the configured public file URL **Files:** - Create: `src/test/java/com/sztzjy/linkCommerce/controller/common/CommonUploadControllerTest.java` - Modify: `src/main/java/com/sztzjy/linkCommerce/controller/common/CommonUploadController.java` **Interfaces:** - Consumes: `IFileUtil.upload(MultipartFile)` returning a relative path such as `/2026/8/1/example.docx`. - Produces: upload result map with `url` and `fileName` equal to `/2026/8/1/example.docx`. - [ ] **Step 1: Write the failing test** ```java @Test void uploadReturnsAbsoluteConfiguredFileUrl() { IFileUtil fileUtil = mock(IFileUtil.class); when(fileUtil.upload(any(MultipartFile.class))).thenReturn("/2026/8/1/example.docx"); CommonUploadController controller = new CommonUploadController(); ReflectionTestUtils.setField(controller, "fileUtil", fileUtil); ReflectionTestUtils.setField(controller, "fileUrl", "https://files.example.com/file/"); Map result = controller.upload(new MockMultipartFile("file", "case.docx", "application/vnd.openxmlformats-officedocument.wordprocessingml.document", "case".getBytes())); assertEquals("https://files.example.com/file/2026/8/1/example.docx", result.get("url")); assertEquals(result.get("url"), result.get("fileName")); } ``` - [ ] **Step 2: Run test to verify it fails** Run: `mvn -Dtest=CommonUploadControllerTest test` Expected: FAIL because the controller currently returns `/file/2026/8/1/example.docx`. - [ ] **Step 3: Write minimal implementation** ```java @Value("${file.url}") private String fileUrl; private String publicFileUrl(String relativePath) { return StringUtils.removeEnd(StringUtils.trimToEmpty(fileUrl), "/") + relativePath; } ``` Use `publicFileUrl(filePath)` for both `url` and `fileName` in the successful upload response. - [ ] **Step 4: Run test to verify it passes** Run: `mvn -Dtest=CommonUploadControllerTest test` Expected: PASS. - [ ] **Step 5: Commit** ```bash git add src/main/java/com/sztzjy/linkCommerce/controller/common/CommonUploadController.java src/test/java/com/sztzjy/linkCommerce/controller/common/CommonUploadControllerTest.java git commit -m "fix: return absolute upload file urls" ```