웹 개발/[KLOZ] 웹 프로젝트

[KLOZ] JasperStudio 에서 Img 를 파라미터로 보낼 때 (HttpServletRequest사용)

cha430 2025. 6. 25. 10:15

정답! 찾음 ㅎ최종!

 

2. classpath 사용한 버전

3. 예전에 뭐 이것저것 시도해봤던 내용

 

 

 

2. classpath 사용

 

이전 연습 프로젝트 만들 때 했던 방법으로 해보니 이번엔 계속 에러가 난다 ..

java.io.IOException: The byte array is not a recognized imageformat.

 

 

 

@Controller
@RequestMapping("/report")
public class ReportController {

	private String signImg = "/image/signImg.png";	// 대표자 서명 이미지.

	@PostMapping("/reportPDF.do")
	public ResponseEntity<byte[]> reportPDF(HttpServletRequest request) throws Exception {
		Map<String, Object> param = new HashMap<String, Object>();

		Integer userSeq = Integer.parseInt(String.valueOf(SessionManager.get(SessionKeys.session_user_seq)));

		String baseUrl = request.getScheme() + "://" +
			request.getServerName() + ":" +
			request.getServerPort() +
			request.getContextPath();

		String signImgUrl = baseUrl + signImg;
		...
		param.put("signImg", signImgUrl);
		...
			return ReportUtils.exportPDF(print, "order_list_");

	}

 

 

http://localhost:포트번호/OrderManager/image/signImg.png

 

signImgUrl 로 생성되는 위 경로로 접속하면 이미지는 뜬다.

그러니 URL 이 문제는 아니라는 이야기고, 결국 jasper 가 받을 때 뭔가 문제가 있다는 뜻..

 

 

 

new java.io.File($P{signImg}).toURI().toURL()

 

image 요소의 Expression 에 이렇게 적어주고

 

당연히 파라미터 signImg 도 String 으로 추가해주고

 

String signImgPath = ResourceUtils.getFile("classpath:static/image/signImg.png").getAbsolutePath();

 

저장 파일 위치

 

 

도장 이미지가 잘 뜬다.

 

 

 

 

 

 

후후. 이전 코드로 똑같이 했을 때 왜 안되는지 찾았다.

바로바로 

Interceptor 때문 !

 

 : Spring Interceptor 설정에서 excludePathPatterns 에 이미지 경로를 추가하는 것은

Interceptor 가 이미지 리소스에 대 한 요청을 가로채지 않도록 하는 것이다.

 

 - Interceptor의 역할
  -> Spring MVC의 Interceptor는 Controller의 메서드를 호출하기 전/후에 로직을 수행할 수 있도록 요청을 가로채는 역할.
주로 인증/권한 확인, 로깅, 세션 관리 등의 공통적인 처리를 위해 사용됨

 - addPathPatterns("/**/*.*", "/**/*")

  -> 이 설정은 모든 URL 요청(.do나 리소스 파일, 일반 경로 포함)에 대해 Interceptor를 적용하겠다는 의미.

 

 

나는 signImgUrl 이라는 변수에 URL 을 담아 사용하는 건데,

Interceptor의 addPathPatterns 가 모든 경로 ("/**/*.*")를 포함하기 때문에

이미지 요청도 Interceptor 를 거치게 된다.

이러면 PDF 도구는 이미지 요청할 때 session 정보가 없기 때문에 제대로 데이터를 가져오지 못한다.

 

그래서 excludepathPatterns 에 "/image/**" 를 추가해서 Interceptor 가 가로채지 않고 통과하도록 만든다.

이러면 정적 리소스 핸들러가 이미지 파일을 즉시 반환한다.

 

 

 

package dev.kloz.weborder.common.config;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

@Configuration
public class WebCustomConfig implements WebMvcConfigurer {

	@Autowired
	CommonInterceptor interceptor;

	@Override
	public void addInterceptors(InterceptorRegistry registry) {
		//		registry.addInterceptor(new DeviceResolverHandlerInterceptor());

		registry.addInterceptor(interceptor)
			.addPathPatterns("/**/*.*", "/**/*")
			.excludePathPatterns("/login/**/*.*", "/common/codeHelp/getLanguageList.do", "/assets/*.*", "/error", "/dev/*.*",
				"/common/doFileDownload/**/*","/image/**");
		//				.excludePathPatterns("/buySCM/notice/**/*.*");

	}

}

 

"/image/**"  로 내가 이미지 저장해둔 경로를 포함시켜주면~ 끝.

 

 

 

 

public class ReportController {

	private String signImg = "/image/signImg.png";
    
    @PostMapping("/reportPDF.do")
    public ResponseEntity<byte[]> reportPDF(HttpServletRequest request) throws Exception {
        Map<String, Object> param = new HashMap<String, Object>();

        Integer userSeq = Integer.parseInt(String.valueOf(SessionManager.get(SessionKeys.session_user_seq)));

        String baseUrl = request.getScheme() + "://" +
           request.getServerName() + ":" +
           request.getServerPort() +
           request.getContextPath();

        String signImgUrl = baseUrl + signImg;
        ...
        param.put("signImg", signImgUrl);
        ...

 

 

 

 







 

 

 

3. 입사 초반 이것 저것 시도한 기록들 .

 

 

.jrxml
<parameter name="klozImg" class="java.lang.String"/>
 

 

public class ReportController {

    private ApplicationContext applicationContext;
    private String klozImg = "https://res.cloudinary.com/dlujvuy6p/image/upload/kloz_giefku.png";

    @GetMapping("/reportPDF.do")
    public ResponseEntity<byte[]> reportPDF(HttpServletRequest request, HttpServletResponse response, HttpSession session) throws Exception{

       Map<String, Object> param = new HashMap<>();

       String loginUserId = (String) session.getAttribute("userId");

       // if (loginUserId == null || loginUserId.isEmpty()) {
       //     loginUserId = "UNKNOWN_USER"; // 로그인 정보가 없을 경우 기본값 설정
       //     log.warn("Session userId not found. Using default: {}", loginUserId);
       // } else {
       //     log.info("Logged in user ID from session: {}", loginUserId);
       // }

       param.put("loginUserId", loginUserId);
       param.put("klozImg", klozImg);

       String mstReportUri = String.valueOf(
          ResourceUtils.getFile("classpath:templates/report/assetsList/assets_list.jrxml"));
       log.debug("mstReportUri ====>>>> {}", mstReportUri);

       DataSource ds = (DataSource)ApplicationContextProvider.getApplicationContext().getBean("dataSource");

       Connection con = ds.getConnection();
       JasperReport report = JasperCompileManager.compileReport(mstReportUri);
       JasperPrint print = JasperFillManager.fillReport(report, param, con);

       ResponseEntity<byte[]> responseEntity = exportPDF(print, "assets_list_");

       con.close();

       return responseEntity;
    }

    @GetMapping("/reportExcel.do")
    public void reportExcel(HttpServletRequest request, HttpServletResponse response, HttpSession session) throws Exception {

       // param : 검색 조건 등 넘기는 용도. JASPER에 $P{}없으면 무시됨
       Map<String, Object> param = new HashMap<>();

       String loginUserId = (String) session.getAttribute("userId");

       // if (loginUserId == null || loginUserId.isEmpty()) {
       //     loginUserId = "UNKNOWN_USER"; // 로그인 정보가 없을 경우 기본값 설정
       //     log.warn("Session userId not found. Using default: {}", loginUserId);
       // } else {
       //     log.info("Logged in user ID from session: {}", loginUserId);
       // }

       param.put("loginUserId", loginUserId);
       param.put("klozImg", klozImg);

       String mstReportUri = String.valueOf(
          ResourceUtils.getFile("classpath:templates/report/assetsList/assets_list.jrxml"));
       log.debug("mstReportUri ====>>>> {}", mstReportUri);

       DataSource ds = (DataSource)ApplicationContextProvider.getApplicationContext().getBean("dataSource");
       Connection con = ds.getConnection();

       JasperReport report = JasperCompileManager.compileReport(mstReportUri);
       JasperPrint print = JasperFillManager.fillReport(report, param, con);

       exportExcel(print, "assets_list_", response);
       con.close();
    }
 
 

 

 

서버 꺼졌을 때도 접근, 다른 사람도 접근 가능하게 하려고 네트리파이랑 클라우디너리 계정도 만들고 별 짓을 다 했지만

https://res.cloudinary.com/dlujvuy6p/image/upload/kloz_giefku.png

 

(이걸 url 파라미터로 넘기면 됨)

 

결국 내가 자리에 없을 때 이미지 파일 수정을 못한다는 단점.

 

그래서 다시 GPT괴롭혔더니~

 

동적 URL 생성 방법이 있다.

 

이건 프로젝트 내 경로를 참조해서 접근할 수 있기 때문에 다른 개발자도 접근 가능하고

내 서버, 내 컴퓨터에 저장한 게 아니니까 다른 브라우저에서도 접근 가능하다.

 

 

String baseUrl = request.getScheme() + "://" +
    request.getServerName() + ":" +
    request.getServerPort();
    
String klozImgUrl = baseUrl + "/images/kloz.png";
	param.put("klozImg", klozImgUrl);

 

 

이렇게 넘기면 된다. Scheme..ServerName.. 전부 Boot 가 제공하는 자동 매핑 기능이라고 한다.

 

 .jrxml 에서는 이렇게 받는다.

<parameter name="klozImg" class="java.lang.String"/>

<element kind="image" uuid="4861f6f2-a861-4fef-8118-f91279d7a84f" x="0" y="0" width="140" height="50">
    <expression><![CDATA[new java.net.URL($P{klozImg})]]></expression>
</element>

 

 

 

 

이렇게하면 끝.

 

아래는 gpt설명..

뭔소린지 몰라서 나중에 천천히 읽어보기

 

 

Spring Boot가 resources/static/ 폴더의 내용을 자동으로 HTTP 경로에 매핑해주는 건,
Spring Boot 자체의 기본 정적 자원 매핑 규칙 때문입니다.
이건 공식 문서에도 명시되어 있는 Spring Boot의 기본 동작이에요.

✅ Spring Boot의 정적 리소스 매핑 규칙
다음 경로에 파일이 있으면 자동으로 서빙됩니다:

폴더 위치	HTTP 경로
classpath:/static/	/ 하위 경로 (예: /images/kloz.png)
classpath:/public/	/ 하위 경로
classpath:/resources/	/ 하위 경로
classpath:/META-INF/resources/	/ 하위 경로

이 규칙에 따라
src/main/resources/static/images/kloz.png 라는 파일은
Spring Boot가 실행되면 자동으로:

bash
복사
편집
http://localhost:8080/images/kloz.png
이렇게 서빙됩니다.

📚 공식 문서 근거
Spring Boot 2.x~3.x 기준 문서:

🔗 Spring Boot Reference: Static Content

By default, Spring Boot serves static content from a number of locations:
/static, /public, /resources, or /META-INF/resources.

💡 직접 실험해보는 방법
src/main/resources/static/images/kloz.png 파일 넣기

Spring Boot 서버 실행

브라우저에서:

bash
복사
편집
http://localhost:8080/images/kloz.png
→ 이미지가 바로 보이면 성공!

✅ 추가 팁
만약 경로를 커스터마이징 하고 싶다면
application.properties에서 다음처럼 경로를 지정할 수도 있어요:

properties
복사
편집
spring.web.resources.static-locations=classpath:/static/
하지만 별도로 설정하지 않으면, 기본 경로는 /static/ 입니다.

✅ 정리
Spring Boot는 resources/static/ 아래의 파일을 자동으로 URL로 노출하고,
그 경로는 http://<host>:<port>/<static 하위 경로> 로 자동 매핑됩니다.
이건 Spring Boot의 기본 기능이라 별도 코드나 설정 없이도 동작합니다.

궁금하시면 예제 프로젝트도 바로 만들어 드릴 수 있어요.

 

 

 

 

 

 

 
*****
이미지가 자주 변경될 땐 @Value써서 이렇게 해도 됨

 

 
YAML
 
report:
  kloz:
    image-url: https://res.cloudinary.com/dlujvuy6p/image/upload/kloz_giefku.png

 

 

import org.springframework.beans.factory.annotation.Value;
// ... 다른 import 문

@Controller
@RequiredArgsConstructor
@RequestMapping(value = "/report", method = RequestMethod.GET)
@Slf4j
public class ReportController {

    @Value("${report.kloz.image-url}") // 설정 파일에서 값을 주입받음
    private String klozImg;

    // ... 나머지 컨트롤러 코드
}