REGEXP_SUBSTR(대상문자열, 정규표현식, 시작위치, 몇번째일치하는것 가져올지, 대소문자구분, 패턴중 몇번째 패턴 가져올지)

 

select juso, REGEXP_SUBSTR(juso, '\d+동 \d+호', 1, 1, 'i' ) as dongho from (
    select '150동 2305호 서울특별시 영등포구 당산로54길 11, 230동 111호(당산동, 래미안당산1차아파트)' as juso from dual
);  --> 150동 2305호

select juso, REGEXP_SUBSTR(juso, '\d+동 \d+호', 1, 2, 'i' ) as dongho from (
    select '150동 2305호 서울특별시 영등포구 당산로54길 11, 230동 111호(당산동, 래미안당산1차아파트)' as juso from dual
); --> 230동 111호

 

select juso, REGEXP_SUBSTR(juso, '(\d+동) (\d+호)', 1, 2, 'i', 1 ) as dongho from (
    select '150동 2305호 서울특별시 영등포구 당산로54길 11, 230동 111호(당산동, 래미안당산1차아파트)' as juso from dual
); --> 230동

 

select juso, REGEXP_SUBSTR(juso, '(\d+동) (\d+호)', 1, 2, 'i', 2 ) as dongho from (
    select '150동 2305호 서울특별시 영등포구 당산로54길 11, 230동 111호(당산동, 래미안당산1차아파트)' as juso from dual
); --> 111호

iframe 안의 콘텐츠 높이에 따라서 iframe의 높이를 조절하는 방식이다.

 

자식에서 자신의 iframe을 선택하는 것은

window.frameElement 로 접근할수 있다.

window.frameElement.height 는 아이프레임의 높이.

document.querySelector("body").clientHeight + 20 자식 body 영역의 높이에 적당한 높이를 더하여 부모 아이프레임 높이를 조절하면 된다.

 

parent.html

<!DOCTYPE html>
<html lang="ko">
<head>
    <title>Parent</title>
</head>
<body>
    <div>
        <iframe src="./child.html"></iframe>
    </div>
</body>
</html>

 

child.html

<!DOCTYPE html>
<html lang="ko">
<head>
    <title>Child</title>
    <script>
        window.onload = function() {
            window.frameElement.height = document.querySelector("body").clientHeight + 20;
        }
    </script>
</head>
<body>
    <div id="content">
        자식 입니다.<br>
        자식 입니다.<br>
        자식 입니다.<br>
        자식 입니다.<br>
        자식 입니다.<br>
        자식 입니다.<br>
        자식 입니다.<br>
        자식 입니다.<br>
        자식 입니다.<br>
        자식 입니다.<br>
        자식 입니다.<br>
        자식 입니다.<br>
        자식 입니다.<br>
    </div>
</body>
</html>

 

주민번호 형식 : 123456-1234567

 

1. 정규식으로 숫자6자리, 대쉬, 숫자7자리 체크

2. 주민번호 체크 로직으로 체크

주민번호 첫자리부터 12번째 자리까지 순서대로 

2,3,4,5,6,7,8,9,2,3,4,5 를 한자리씩 곱해서 모두 더한다.

모두 더한값을 11로 나누어 나머지를 구한다.

11에서 나머지를 뺀 값이 주민번호의 마지막 번호와 같으면 유효하다.

ex) sum = 1*2 + 2*3 + 3*4 + 4*5 + 5*6 + 6*7 + 1*8 + 2*9 + 3*2 + 4*3 + 5*4 + 6*5 = 206

나머지 = 206 % 11 = 8

값 = 11 - 8 = 3

주민번호 마지막은 7이므로 유효하지 않음.

 

// 주민번호 체크
function isResidentRegNoValid(residentRegNo) {
	var re = /^[0-9]{6}-[0-9]{7}$/;
	if (!re.test(String(residentRegNo).toLowerCase())) {
		return false;
	}

	var regNos = residentRegNo.replace('-', '').split('');
	var checkNos = [2,3,4,5,6,7,8,9,2,3,4,5];
	var sum = 0;
	for (var i = 0; i < checkNos.length; i++) {
		sum = sum + (checkNos[i] * Number(regNos[i]));
	}
	return ((11 - (sum % 11)) % 10) == Number(regNos[12]);
}

 

 

 

 

 

외부 서버에서 파일을 ByteArrayInputStream으로 받아서 서버에 물리적으로 저장하는 방법

 

 

void org.apache.commons.io.FileUtils.copyInputStreamToFile(InputStream source, File destination) throws IOException

 

아파치 커먼 IOd에 있는 FileUtils 클래스를 이용하여 저장하면 된다.

 

FileUtils.copyInputStreamToFile(인풋스트림, 파일객체);

스프링에서 파라미터 유효성 검사를 위한 커스터 마이징

날짜형식의 String을 유효성 체크 하기 위한 커스터 마이징

날짜형식 : 2021-09-10

 

1. 의존성 추가

 

<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-validation</artifactId>
</dependency>

 

2. 사용자 정의 어노테이션을 위한 인터페이스 생성

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

import javax.validation.Constraint;
import javax.validation.Payload;

@Documented
@Constraint(validatedBy = DateValidator.class)
@Target( {ElementType.METHOD, ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
public @interface DateValid {
    String message() default "날짜형식이 옳바르지 않습니다.";
    Class<?>[] groups() default {};
    Class<? extends Payload>[] payload() default {};
}

 

3. 유효성 검사를 실행할 클래스 생성

import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeParseException;

import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;

public class DateValidator implements ConstraintValidator<DateValid, String>{

    @Override
    public void initialize(DateValid constraintAnnotation) {

    }

    @Override
    public boolean isValid(String value, ConstraintValidatorContext context) {
        if (value == null ||  value.length() == 0) return true;
        try {
            LocalDate.from(LocalDate.parse(value, DateTimeFormatter.ofPattern("yyyy-MM-dd")));
        } catch (DateTimeParseException e) {
            e.printStackTrace();
            return false;
        }
        return true;
    }
}

 

4. DTO에 사용자 정의 유효성 검사 어노테이션 추가

 

@DateValid(message = "날짜형식이 옳바르지 않습니다.")
private String date;

 

 

hls.html

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<link href="https://vjs.zencdn.net/7.11.4/video-js.css" rel="stylesheet" />
<script src="https://vjs.zencdn.net/7.11.4/video.min.js"></script>
</head>
<body>
<video id="video" class="video-js" controls="controls" width="400" autoplay="autoplay"></video>


<script th:inline="javascript">
/*<![CDATA[*/
var videoUrl = /*[[ ${videoUrl} ]]*/;
/*]]*/
videojs.Vhs.xhr.beforeRequest = function (options) {
    options.headers = {
        Authorization: 'Bearer ' + "userToken"
    };
    return options;
};
var $vplay = videojs("video");
$vplay.src({
	src : videoUrl,
	type: "application/x-mpegurl"
});
</script>
  
</body>
</html>

 

 

java

	@GetMapping("/hls-make/{fileName}")
	@ResponseBody
	public void videoHlsMake(@PathVariable String fileName, Model model) throws IOException {
		log.debug("************** class = {}, function = {}", this.getClass().getName(), new Object(){}.getClass().getEnclosingMethod().getName());
		
    	final String FFMPEG_PATH = ffmpegProperties.getPath();
    	final String FFMPEG = ffmpegProperties.getFfmpeg();
    	final String FFPROBE = ffmpegProperties.getFfprobe();
    	final String FILEPATH = UPLOAD_DIR + "/" + fileName;
    	final String ONLY_FILENAME = fileName.substring(0, fileName.lastIndexOf("."));
    	final String TS_PATH = UPLOAD_DIR + "/" + ONLY_FILENAME;
    	File tsPath = new File(TS_PATH);
    	if(!tsPath.exists()) {
    		tsPath.mkdir();
    	}
    	
		FFmpeg ffmpeg = new FFmpeg(FFMPEG_PATH + "/" + FFMPEG);
		FFprobe ffprobe = new FFprobe(FFMPEG_PATH + "/" + FFPROBE);
		
        FFmpegProbeResult probeResult = ffprobe.probe(FILEPATH);

        
        log.debug("========== VideoFileUtils.getMediaInfo() ==========");
        log.debug("filename : {}", probeResult.getFormat().filename);
        log.debug("format_name : {}", probeResult.getFormat().format_name);
        log.debug("format_long_name : {}", probeResult.getFormat().format_long_name);
        log.debug("tags : {}", probeResult.getFormat().tags.toString());
        log.debug("duration : {} second", probeResult.getFormat().duration);
        log.debug("size : {} byte", probeResult.getFormat().size);
        log.debug("width : {} px", probeResult.getStreams().get(0).width);
        log.debug("height : {} px", probeResult.getStreams().get(0).height);
        log.debug("===================================================");
		
        // TS 파일 생성
        FFmpegBuilder builder = new FFmpegBuilder()
        			//.overrideOutputFiles(true) // 오버라이드 여부
        			.setInput(FILEPATH) // 동영상파일
        			.addOutput(TS_PATH + "/" + ONLY_FILENAME + ".m3u8") // 썸네일 경로
        			.addExtraArgs("-profile:v", "baseline") // 
        			.addExtraArgs("-level", "3.0") //
        			.addExtraArgs("-start_number", "0") //
        			.addExtraArgs("-hls_time", "10") //
        			.addExtraArgs("-hls_list_size", "0") //
        			.addExtraArgs("-f", "hls") //
        			.done();
        FFmpegExecutor executor = new FFmpegExecutor(ffmpeg, ffprobe);
        executor.createJob(builder).run();
        
        
        // 이미지 파일 생성
        FFmpegBuilder builderThumbNail = new FFmpegBuilder()
    			.overrideOutputFiles(true) // 오버라이드 여부
    			.setInput(FILEPATH) // 동영상파일
    			.addExtraArgs("-ss", "00:00:03") // 썸네일 추출 싲가점
    			.addOutput(UPLOAD_DIR + "/" + ONLY_FILENAME + ".png") // 썸네일 경로
    			.setFrames(1) // 프레임 수
    			.done();
        FFmpegExecutor executorThumbNail = new FFmpegExecutor(ffmpeg, ffprobe);
        executorThumbNail.createJob(builderThumbNail).run();
        
		model.addAttribute("result", "OK");
	}
	
	
	@GetMapping("/hls")
	public String videoHls(Model model) {
		log.debug("************** class = {}, function = {}", this.getClass().getName(), new Object(){}.getClass().getEnclosingMethod().getName());
		model.addAttribute("videoUrl", "/video/hls/video/video.m3u8");
		return TEMPLATE_DIR + "hls";
	}
	
	@GetMapping("/hls/{fileName}/{fileName}.m3u8")
	public ResponseEntity<Resource> videoHlsM3U8(@PathVariable String fileName) {
		log.debug("************** class = {}, function = {}", this.getClass().getName(), new Object(){}.getClass().getEnclosingMethod().getName());
		String fileFullPath = UPLOAD_DIR + fileName + "/" + fileName + ".m3u8";
		Resource resource = new FileSystemResource(fileFullPath); 
		HttpHeaders headers = new HttpHeaders();
		headers.set(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=" + fileName + ".m3u8");
		headers.setContentType(MediaType.parseMediaType("application/vnd.apple.mpegurl"));
		return new ResponseEntity<Resource>(resource, headers, HttpStatus.OK);
	}
	
	@GetMapping("/hls/{fileName}/{tsName}.ts")
	public ResponseEntity<Resource> videoHlsTs(@PathVariable String fileName, @PathVariable String tsName) {
		log.debug("************** class = {}, function = {}", this.getClass().getName(), new Object(){}.getClass().getEnclosingMethod().getName());
		String fileFullPath = UPLOAD_DIR + fileName + "/" + tsName + ".ts";
		Resource resource = new FileSystemResource(fileFullPath); 
		HttpHeaders headers = new HttpHeaders();
		headers.set(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=" + tsName + ".ts");
		headers.setContentType(MediaType.parseMediaType(MediaType.APPLICATION_OCTET_STREAM_VALUE));
		return new ResponseEntity<Resource>(resource, headers, HttpStatus.OK);
	}

 

pom.xml

		<!-- ffmpeg 동영상 인코더 연결 라이브러리 -->
		<dependency>
		  <groupId>net.bramp.ffmpeg</groupId>
		  <artifactId>ffmpeg</artifactId>
		  <version>0.6.2</version>
		</dependency>

 

 

https://www.ffmpeg.org/download.html

 

Download FFmpeg

If you find FFmpeg useful, you are welcome to contribute by donating. More downloading options Git Repositories Since FFmpeg is developed with Git, multiple repositories from developers and groups of developers are available. Release Verification All FFmpe

www.ffmpeg.org

 

이클립스 UTF-8설정을 안하고 프로젝트를 임포트하는 경우

html,css,jsp 파일등이 euc-kr 로 설정된느 경우가 있다.

 

파일 하나씩 열어서 UTF-8로 변경하거나 프로젝트 삭제 후 다시 임포트 하면 되지만

한번에 모든 파일을 UTF-8로 업데이트 하는 방법이 있다.

 

메뉴 > Window > Preferences > General > Content Types 메뉴에서

Text 를 클릭하고 하단의 Default encoding 항목에 UTF-8을 입력하고

Update 버튼을 클릭하면 모든 파일이 UTF-8로 업데이트 된다.

 

업데이트하는데 시간이 좀 걸리니 조금 있다 파일을 다시 열어보면 깨져있던 한글이 정상적으로 보인다.

 

 

 

angular, primeng - p-overlayPanel 위치가 정상적이지 않을때

 

<div #overlayTarget>

    <button type="text" pButton label="Basic" (click)="op.toggle($event)"></button>

</div>
<p-overlayPanel #op [appendTo]="overlayTarget">
    <ng-template pTemplate>
        레이어 내용입니다.
    </ng-template>
</p-overlayPanel>

 

appendTo 속성에 타겟을 설정해 주면 된다.

 

 

익스플로러11에서

primeng p-fieldset 사용시

레이어팝업처럼 본문 넓이보다 넓이가 작은 레이어에서

p-fieldset 사용시 팝업보다 width가 커지는 문제가 발생

 

css 파일에 아래의 속성 추가하여 해결

 

fieldset {
    width: intrinsic;
}

LocalDateTime format, pattern으로 변환하여 표현하기

 

패턴, 포맷별 출력 형식이다.

 

LocalDateTime date = LocalDateTime.now(

date.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSS"))
// 2021-09-02 14:56:20.669

date.format(DateTimeFormatter.BASIC_ISO_DATE)
// 20210902
date.format(DateTimeFormatter.ISO_DATE)
// 2021-09-02
date.format(DateTimeFormatter.ISO_DATE_TIME)
// 2021-09-02T14:56:20.669
date.format(DateTimeFormatter.ISO_INSTANT)
// ERROR
date.format(DateTimeFormatter.ISO_LOCAL_DATE)
// 2021-09-02
date.format(DateTimeFormatter.ISO_LOCAL_DATE_TIME)
// 2021-09-02T14:56:20.669
date.format(DateTimeFormatter.ISO_OFFSET_DATE)
// ERROR
date.format(DateTimeFormatter.ISO_OFFSET_DATE_TIME)
// ERROR
date.format(DateTimeFormatter.ISO_ORDINAL_DATE)
// 2021-245
date.format(DateTimeFormatter.ISO_TIME)
// 14:56:20.669
date.format(DateTimeFormatter.ISO_WEEK_DATE)
// 2021-W35-4
date.format(DateTimeFormatter.ISO_ZONED_DATE_TIME)
// ERROR
date.format(DateTimeFormatter.RFC_1123_DATE_TIME)
// ERROR

date.format(DateTimeFormatter.ofLocalizedDate(FormatStyle.FULL))
// 2021년 9월 2일 목요일
date.format(DateTimeFormatter.ofLocalizedDate(FormatStyle.LONG))
// 2021년 9월 2일 (목)
date.format(DateTimeFormatter.ofLocalizedDate(FormatStyle.MEDIUM))
// 2021. 9. 2
date.format(DateTimeFormatter.ofLocalizedDate(FormatStyle.SHORT))
// 21. 9. 2

date.format(DateTimeFormatter.ofLocalizedTime(FormatStyle.FULL))
// ERROR
date.format(DateTimeFormatter.ofLocalizedTime(FormatStyle.LONG))
// 오후 2시 56분 20초
date.format(DateTimeFormatter.ofLocalizedTime(FormatStyle.MEDIUM))
// 오후 2:56:20
date.format(DateTimeFormatter.ofLocalizedTime(FormatStyle.SHORT))
// 오후 2:56

date.format(DateTimeFormatter.ofLocalizedDateTime(FormatStyle.FULL))
// ERROR
date.format(DateTimeFormatter.ofLocalizedDateTime(FormatStyle.LONG))
// 2021년 9월 2일 (목) 오후 2시 56분 20초
date.format(DateTimeFormatter.ofLocalizedDateTime(FormatStyle.MEDIUM))
// 2021. 9. 2 오후 2:56:20
date.format(DateTimeFormatter.ofLocalizedDateTime(FormatStyle.SHORT))
// 21. 9. 2 오후 2:56

 

+ Recent posts