반응형

스프링부트에서 STOMP를 이용한 메세지 pub/sub 예시

build.gradle에서 라이브러리를 추가해주십쇼 

implementation 'org.springframework.boot:spring-boot-starter-websocket'

 

웹소켓 설정파일 WebsocketConfig.java 을 아래와 같은 내용으로 생성

import org.springframework.context.annotation.Configuration;
import org.springframework.messaging.simp.config.MessageBrokerRegistry;
import org.springframework.web.socket.config.annotation.EnableWebSocket;
import org.springframework.web.socket.config.annotation.EnableWebSocketMessageBroker;
import org.springframework.web.socket.config.annotation.StompEndpointRegistry;
import org.springframework.web.socket.config.annotation.WebSocketConfigurer;
import org.springframework.web.socket.config.annotation.WebSocketHandlerRegistry;
import org.springframework.web.socket.config.annotation.WebSocketMessageBrokerConfigurer;
import lombok.RequiredArgsConstructor;

@Configuration
@EnableWebSocketMessageBroker
@RequiredArgsConstructor
public class WebsocketConfig implements WebSocketMessageBrokerConfigurer {

@Override
    public void configureMessageBroker(MessageBrokerRegistry registry){
        // /pub으로 시작하는 요청은 @Controller의 @MessageMapping 메소드로 라우트됨
        // 클라이언트가 서버로 메세지를 보낼 때 붙여야하는 prefix
        registry.setApplicationDestinationPrefixes("/pub"); 

         //해당 문자열로 시작하는 message 주소값을 받아서 처리하는 Broker를 활성화한다.
        registry.enableSimpleBroker("/sub"); //메세지 구독 주소값
    }

    @Override
    public void registerStompEndpoints(StompEndpointRegistry registry){
        registry.addEndpoint("/websocket")  //클라이언트가 연결할 url
        .setAllowedOriginPatterns("*")
        .withSockJS(); 
        //withSockJS : 웹소켓을 지원하지 않는 환경에서도 웹소켓 사용을 가능하게 해주는 옵션
        //이 옵션을 달면 클라이언트에서 SockJS 라이브러리를 사용해야 함
        //http 아니면 https 로 연결가능(sockJS가 http를 ws로 변환해줌)
    }
}

 

서버에서 STOMP 메세지 보내기

- convertAndSend 메소드를 호출하면 클라이언트가 구독하고 있는 주소로 메세지가 발행됨.

- /sub/** 주소를 구독하고 있는 클라이언트에게 메세지를 전달하는 예시 

import java.util.HashMap;
import java.util.Map;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.messaging.simp.SimpMessagingTemplate;
import org.springframework.stereotype.Component;
import lombok.RequiredArgsConstructor;


@Component
@RequiredArgsConstructor
public class sendService{
    private final SimpMessagingTemplate messagingTemplate;

    public void sendMessageToSubOrderTopic(String message,String id) {
        messagingTemplate.convertAndSend("/sub/"+id, message);
    }
}

 

 

 

서버에서 STOMP 메세지 받아서 전달하기

- 서버가 메세지 브로커 역할 수행

- 특정 클라이언트가 /sub/test 주소로 메세지를 보내면 @MessageMapping에서 받아 @SendTo에 설정된 쪽으로 전달

- /sub/** 을 구독하는 클라이언트가 메세지를 받아볼 수 있는 예시

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.messaging.handler.annotation.DestinationVariable;
import org.springframework.messaging.handler.annotation.MessageMapping;
import org.springframework.messaging.handler.annotation.SendTo;
import org.springframework.messaging.simp.SimpMessagingTemplate;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@Controller
public class StompMessageController {
/* 클라이언트에서 웹소켓을 연결한 뒤 /pub/test 로 메세지를 보내면
 여기서 받아 SendTo에 명시된 구독 링크로 메세지를 발행
 prefix는 생략
*/
    @MessageMapping("/test")
    @SendTo("/sub")
    public String processMessage(String message){
        System.out.println("message : " + message);
        return message;

    }

    //STOMP를 쓰면 좋은점
   	/* @Controller 적용된 객체를 이용해 조직적으로 관리할 수 있다.
    	STOMP의 Destination 경로를 기반으로 Spring Security를 적용할 수 있다
    	외부 브로커를 이용해 여러 서버를 관리할 수 있다.
    */


}

 


그럼 메세지를 구독하고 보내는 클라이언트 페이지를 띄워 테스트를 해보자..

검색해보면 전부 다 APIC으로 테스트를 하던데 APIC자체를 못찾아서 javascript로 짜서 했음. 

html 페이지에 javascript 소스를 넣는다.

 

메세지 구독하는 클라이언트 페이지 소스 예시 (javascript)

서버에 withSockJS() 설정이 되어있다면 SockJS 를 이용하여 연결해야 하며 이 경우엔 http나 https 로 접속을 해야함.

서버에서 /sub 주소로 구독하고 있는 클라이언트에 메세지를 전달해주므로 

/sub/aaa이나  /sub/bbb 를 구독하는 쪽은 메세지를 다 받을 수 있음. 

<script src="https://cdnjs.cloudflare.com/ajax/libs/sockjs-client/1.6.1/sockjs.min.js" integrity="sha512-1QvjE7BtotQjkq8PxLeF6P46gEpBRXuskzIVgjFpekzFVF4yjRgrQvTG1MTOJ3yQgvTteKAcO7DSZI92+u/yZw==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/stomp.js/2.3.3/stomp.min.js"></script>

<script type="text/javascript">
var socket = new SockJS("http://localhost:8081/websocket");
stompClient = Stomp.over(socket);
stompClient.connect({}, function (frame) {
    console.log("연결 완료");
    stompClient.subscribe("/sub/aaa",function(response){
        console.log(response.body);
  });	
});
</script>

 

메세지를 발행하는 클라이언트 페이지 소스 예시(javascript)

<script src="https://cdnjs.cloudflare.com/ajax/libs/sockjs-client/1.6.1/sockjs.min.js" integrity="sha512-1QvjE7BtotQjkq8PxLeF6P46gEpBRXuskzIVgjFpekzFVF4yjRgrQvTG1MTOJ3yQgvTteKAcO7DSZI92+u/yZw==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/stomp.js/2.3.3/stomp.min.js"></script>

<script type="text/javascript">
var socket = new SockJS("http://localhost:8081/websocket");
stompClient = Stomp.over(socket);
stompClient.connect({}, function (frame) {
    console.log("연결 완료");
    stompClient.send("/pub/test",{},"test메시지입니다.");
});
</script>

 

SockJS를 안 쓰고 싶다면

서버에서 해당 설정을 없애주고

클라이언트에서는 stomp 라이브러리로 바로 연결하면 댐

<script src="https://cdnjs.cloudflare.com/ajax/libs/sockjs-client/1.6.1/sockjs.min.js" integrity="sha512-1QvjE7BtotQjkq8PxLeF6P46gEpBRXuskzIVgjFpekzFVF4yjRgrQvTG1MTOJ3yQgvTteKAcO7DSZI92+u/yZw==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/stomp.js/2.3.3/stomp.min.js"></script>
<script type="text/javascript">
var client = Stomp.client("ws://localhost:8081/websocket");
client.connect({},function(){
    console.log("연결 완료");
    client.subscribe("/sub/aaa",function(message){
        console.log("받은 메세지 : " + mesasge);
    });
})
	
</script>
반응형
반응형

1. websocket 연결설정

import org.springframework.context.annotation.Configuration;
import org.springframework.web.socket.config.annotation.EnableWebSocket;
import org.springframework.web.socket.config.annotation.WebSocketConfigurer;
import org.springframework.web.socket.config.annotation.WebSocketHandlerRegistry;

import lombok.RequiredArgsConstructor;

@Configuration
@EnableWebSocket
@RequiredArgsConstructor
public class WebSocketConfig implements WebSocketConfigurer{

    //밑에서 만들 WebSocketHandler 클래스
    private final WebSocketHandler webSocketHandler;

    @Override
    public void registerWebSocketHandlers(WebSocketHandlerRegistry registry){
        registry.addHandler(webSocketHandler,"/websocket").setAllowedOrigins("*");
        // /websocket : 연결url
        //setAllowedOrigins : 웹소켓 cors정책으로, 허용 도메인 지정
        
    }

}

 

2. websocket 핸들러 생성. web socket 연결 및 종료의 수행에 대한 내용

import java.util.concurrent.ConcurrentHashMap;

import org.springframework.stereotype.Component;
import org.springframework.web.socket.CloseStatus;
import org.springframework.web.socket.TextMessage;
import org.springframework.web.socket.WebSocketSession;
import org.springframework.web.socket.handler.TextWebSocketHandler;

@Component
//TextWebSocketHandler 상속 시 3개의 메소드 오버라이딩
public class WebSocketHandler extends TextWebSocketHandler{
    
    //ConcurrentHashMap : 멀티 스레드 환경에서 사용. entry 아이템별로 락을 건다.
    private static final ConcurrentHashMap<String, WebSocketSession> CLIENTS = new ConcurrentHashMap<String, WebSocketSession>();
    
    public void afterConnectionEstablished(WebSocketSession session)throws Exception{
        CLIENTS.put(session.getId(), session);
        System.out.println("session Id(" + session.getId() + ") 연결");
        //출력예시 : session Id(84693265-e147-0b2c-5505-b2d3c62e62b4) 연결
    }

    @Override
    public void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception{
        CLIENTS.remove(session.getId());
        System.out.println("session Id(" + session.getId() + ") 연결해제");
        //출력예시 : session Id(03017781-abf2-bc66-855e-f217bb99b275) 연결해제
    }

    @Override
    protected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception{
        String id = session.getId();
        System.out.println(CLIENTS.toString());
        //출력예시 : {03017781-abf2-bc66-855e-f217bb99b275=StandardWebSocketSession[id=03017781-abf2-bc66-855e-f217bb99b275, uri=ws://localhost:8081/websocket]}
        CLIENTS.entrySet().forEach(arg ->{
            if(!arg.getKey().equals(id)){
                try{
                    arg.getValue().sendMessage(message);
                }catch(Exception e){
                    e.printStackTrace();
                }
            }
        });
    }
}

 

 

 

테스트 방법

1. chrome에서 제공하는 확장 프로그램 이용

https://chromewebstore.google.com/detail/websocket-test-client/fgponpodhbmadfljofbimhhlengambbn?pli=1

 

2. postman에서 제공하는 웹소켓 연결 기능 이용

반응형
반응형

Spring boot 기반의 웹 어플리케이션에서 Amazon MSK 을 IAM 인증방식으로 연동하려고 함

MSK 클러스터 접속에 사용할 IAM 계정 : test-user ( MSK 관련 권한이 부여되어 있어야 함)

 

사용한 라이브러리

implementation 'org.springframework.kafka:spring-kafka:3.0.12'
implementation 'software.amazon.msk:aws-msk-iam-auth:2.0.3'

 

메세지 전송용 ProducerFactory 생성

KafkaAdmin 클라이언트는 생성하지 않았음
 * ProducerFactory : Kafka Producer 인스턴스를 생성하는 팩토리 빈
* Kafka Producer : Kafaka 브로커에 메시지를 전송하는 역할을 담당

@Bean
public ProducerFactory<String, String> producerFactory() {
     
        Map<String, Object> configProps = new HashMap<>();
        
        //연결할 kafka 브로커설정(MSK 서버)
        configProps.put(ProducerConfig.BOOTSTRAP_SERVERS_CONFIG, kafkaBootstrapServers);
        
        //보내는 메시지 타입 설정     
        configProps.put(ProducerConfig.KEY_SERIALIZER_CLASS_CONFIG, StringSerializer.class);
        configProps.put(ProducerConfig.VALUE_SERIALIZER_CLASS_CONFIG, StringSerializer.class);  

        //IAM인증 설정
        configProps.put(AdminClientConfig.SECURITY_PROTOCOL_CONFIG, "SASL_SSL");
        configProps.put(SaslConfigs.SASL_MECHANISM, "AWS_MSK_IAM");
        //awsProfileName 으로 계정명 명시
        configProps.put(SaslConfigs.SASL_JAAS_CONFIG,"software.amazon.msk.auth.iam.IAMLoginModule required awsProfileName=\"test-user\";");
        configProps.put(SaslConfigs.SASL_CLIENT_CALLBACK_HANDLER_CLASS, "software.amazon.msk.auth.iam.IAMClientCallbackHandler");
                
        return new DefaultKafkaProducerFactory<>(configProps);
}

//위에서 생성한 ProducerFactory로 KafkaTemplate 생성
@Bean
 public KafkaTemplate<String, String> kafkaTemplate() {
        return new KafkaTemplate<>(producerFactory());
}

토픽 생성은 하지 않았음. 특정 토픽으로 메세지를 보낼 때 해당토픽이 존재하지 않으면 자동으로 토픽이 생성됨
auto.create.topics.enable 설정이 디폴트로 true 값을 가짐 

 

메세지 전송용 Service 생성

@Service
public class KafkaProduceService {
    @Autowired
    private KafkaTemplate<String, String> kafkaTemplate;

	//이 메소드를 호출해서 메세지를 보내면 됨
    public void sendMessage(String topic, String message) {
        kafkaTemplate.send(topic, message);
    }  

}

 

 

 

반응형

 

 

메세지 수신용 ConsumerFactory 생성

 * ConsumerFactory : Kafka Consumer 인스턴스를 생성하기 위한 팩토리 빈

 @Bean
 public ConsumerFactory<String, String> consumerFactory() {

        Map<String, Object> configProps = new HashMap<>();
        //consumer Group Id 부여해주기
        configProps.put(ConsumerConfig.GROUP_ID_CONFIG, "testGroup1");
        
        //MSK 브로커 설정(MSK서버)
        configProps.put(ConsumerConfig.BOOTSTRAP_SERVERS_CONFIG, kafkaBootstrapServers);

	//IAM 인증 
        configProps.put(AdminClientConfig.SECURITY_PROTOCOL_CONFIG, "SASL_SSL");
        configProps.put(SaslConfigs.SASL_MECHANISM, "AWS_MSK_IAM");
        configProps.put(SaslConfigs.SASL_JAAS_CONFIG,"software.amazon.msk.auth.iam.IAMLoginModule required awsProfileName=\"test-user\";");
        configProps.put(SaslConfigs.SASL_CLIENT_CALLBACK_HANDLER_CLASS, "software.amazon.msk.auth.iam.IAMClientCallbackHandler");

        configProps.put(ConsumerConfig.KEY_DESERIALIZER_CLASS_CONFIG, StringDeserializer.class.getName());
        configProps.put(ConsumerConfig.VALUE_DESERIALIZER_CLASS_CONFIG, StringDeserializer.class.getName());
        
        return new DefaultKafkaConsumerFactory<>(configProps);
 }

   
//kafka 메시지를 수신하는 리스너 컨테이너를 생성하는데 사용되는 인터페이스
@Bean
public ConcurrentKafkaListenerContainerFactory<String, String> kafkaListenerContainerFactory() {
        ConcurrentKafkaListenerContainerFactory<String, String> factory =
                new ConcurrentKafkaListenerContainerFactory<>();
        factory.setConsumerFactory(consumerFactory());
        return factory;
}

 

 

메세지 수신용 Service 생성

@Service
public class KafkaConsumeService {
    @Autowired
    private KafkaTemplate<String, String> kafkaTemplate;
    
    @KafkaListener(topics = "testTopic", groupId = "testGroup1")
    public void listen(ConsumerRecord<String, String> record) {
        System.out.println(record.value());
        System.out.println(record.toString());
    }

}

 


MSK 에 IAM 인증 시도시 오류 정리

1. IAM 계정의 access key와 secret key를 찾지 못하는 경우

com.amazonaws.SdkClientException: Unable to load AWS credentials from any provider in the chain: [software.amazon.msk.auth.iam.internals.EnhancedProfileCredentialsProvider@3bf917a2: Profile file contained no credentials for profile 'testUser': ProfileFile(profilesAndSectionsMap=[]), cohttp://m.amazonaws.auth.AWSCredentialsProviderChain@2dadd688: Unable to load AWS credentials from any provider in the chain: [EnvironmentVariableCredentialsProvider: Unable to load AWS credentials from environment variables (AWS_ACCESS_KEY_ID (or AWS_ACCESS_KEY) and AWS_SECRET_KEY (or AWS_SECRET_ACCESS_KEY)), SystemPropertiesCredentialsProvider: Unable to load AWS credentials from Java system properties (aws.accessKeyId and aws.secretKey), WebIdentityTokenCredentialsProvider: You must specify a value for roleArn and roleSessionName, software.amazon.msk.auth.iam.internals.EnhancedProfileCredentialsProvider@68aac71d: Profile file contained no credentials for profile 'default': ProfileFile(profilesAndSectionsMap=[]), cohttp://m.amazonaws.auth.EC2ContainerCredentialsProviderWrapper@69883287: Failed to connect to service endpoint: ]]

시스템 환경변수에 AWS_ACCESS_KEY_ID(혹은 AWS_ACCESS_KEY ) 와 AWS_SECRET_KEY (혹은 AWS_SECRET_ACCESS_KEY) 이름으로 access key와 secret key를 세팅해준다. 

혹은 producerFactory와 consumerFactory 내에 System.setProperty로 키 세팅해주면 됨.

System.setProperty("aws.accessKeyId", awsAccessKey);
System.setProperty("aws.secretKey", awsSecretKey);

 

 

2. IAM인증 설정이 바르지 않을때 난 에러 

Node -1 disconnected.
2024-01-31 10:16:24,725 [INFO  ] NetworkClient.cancelInFlightRequests(NetworkClient.java:344) - [Producer clientId=producer-1] Cancelled in-flight API_VERSIONS request with correlation id 1 due to node -1 being disconnected (elapsed time since creation: 98ms, elapsed time since send: 98ms, request timeout: 30000ms)
2024-01-31 10:16:24,726 [WARN  ] NetworkClient$DefaultMetadataUpdater.handleServerDisconnect(NetworkClient.java:1105) - [Producer clientId=producer-1] Bootstrap broker sdfssdfdf.kafka.ap-northeast-2.amazonaws.com:9098 (id: -1 rack: null) disconnected

Factory 생성 시에 sasl_jaas_config 값에 IAM로그인모듈 설정과 IAM계정의 이름을 적어주자.

configs.put(SaslConfigs.SASL_JAAS_CONFIG,"software.amazon.msk.auth.iam.IAMLoginModule required awsProfileName=\"testUser\";");

 

반응형
반응형

버전 : 자바17

내 컨트롤러 메소드..

@GetMapping(value = "/info/{a1}")
    public void getInfo(@PathVariable String a1) throws Exception {
}

이 api를 호출하면 아래와 같은 에러가 나는 것이었다

java.lang.IllegalArgumentException: Name for argument of type [java.lang.String] not specified, and parameter name information not found in class file either.

 

path parameter와 변수명이 같으면 name을 명시 안 해줘도 되는걸로 알고있었는데

컴파일 모드가 debug 모드가 아닌 경우 컴파일 시 로컬 지역변수가 포함이 안 되어 변수 맵핑을 못 한다고 함.

 

컨트롤러 메소드에 name옵션 추가해줌.. 

@GetMapping(value = "/info/{a1}")
    public void getInfo(@PathVariable(name="a1") String a1) throws Exception {
}

 

아니면 컴파일 시 지역변수 포함하도록 build.gradle 파일을 손봐준다.

셋중에 하나 추가 

java {
    options.compilerArgs << "-g"
}


tasks.withType(JavaCompile) {
   options.compilerArgs.add("-parameters")
}


compileJava {
    options.compilerArgs <<  '-parameters'
}

 

반응형
반응형

HTTP 422 / 422 에러 / 422 Unprocessable Entity

요청을 잘 받았으나 문법 오류로 인하여 무언가를 응답할 수 없을때 발생한다고 함

 

원인)

HttpsURLConnection  사용시에 GET 으로 보내면서 데이터를 같이 보내서..

 

[원래 코드]

HttpsURLConnection conn = (HttpsURLConnection) url.openConnection();
conn.setRequestMethod("GET");
conn.setDoOutput(true);

BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(conn.getOutputStream()));
bw.write("abc");
bw.flush();
bw.close();

 

[수정 후]

setDoOutput을 지워주고
출력 스트림을 없앴음.

HttpsURLConnection conn = (HttpsURLConnection) url.openConnection();
conn.setRequestMethod("GET");



setDoOutput 
URLConnection에 대한 doOutput 필드값 설정
URL 연결을 출력용으로 사용하려는 경우 DoOutput 플래그를 true로 설정하고,
그렇지 않은 경우는 false로 설정해야 한다. 기본값은 false이므로 안쓰면 false 임

반응형
반응형

프론트페이지(jsp) => controller 에 폼데이터를 전송할때

데이터를 받아보니 문자가 자동 escape 처리가 되어있었다.

'  는  &#39;

"  는 &quot;

<&lt;

>&gt; 로 바뀌어 전달되었다.

근데 어떤 페이지에서 보낸건 escape 처리가 안 되고 어떤 페이지에서 보낸 건 escape 처리가 되어있었다.

ajax로 보낸건 자동 이스케이프가 안 되는데 form을 만들어서 submit한건 자동 이스케이프 처리가 되는거임..

확인해보니 전송하는 데이터의 Content-Typetext/html인 경우 escape 처리가 되는 듯 함.

 

자세한 설명 ..

text/html 콘텐츠에서는 특수 문자(예: `<`, `>`, `&` 등)가 올바르게 표시되고 HTML 문서의 구조를 방해하지 않도록 하기 위해 문자 이스케이프가 사용됩니다. 예를 들어, `<` 문자는 `&lt;`로, `>` 문자는 `&gt;`로, `&` 문자는 `&amp;`로 이스케이프됩니다. 이는 이러한 문자가 HTML 태그나 엔터티로 해석되는 것을 방지하기 위해 수행됩니다.

반면 application/json 콘텐츠에서 문자 이스케이프는 주로 JSON 형식 자체로 표현되는 데이터와 관련이 있습니다. JSON에는 JSON 파서에서 데이터가 올바르게 구문 분석되고 해석되도록 하기 위해 문자열 내의 문자를 이스케이프하는 자체 규칙이 있습니다. 예를 들어 JSON 문자열 내의 큰따옴표(`"`)와 같은 특수 문자는 `\"`로 이스케이프되고 개행 문자는 `\n`으로 표시됩니다.

 

반응형
반응형

가상환경 생성 전 필요한 패키지 설치

pip install ./configparser-4.0.2-py2.py3-none-any.whl
pip install ./contextlib2-0.6.0.post1-py2.py3-none-any.whl
pip install ./zipp-1.2.0-py2.py3-none-any.whl
pip install ./typing-3.10.0.0-py2-none-any.whl
pip install ./six-1.16.0-py2.py3-none-any.whl
pip install ./scandir-1.10.0-cp27-cp27m-win_amd64.whl
pip install ./pathlib2-2.3.7.post1-py2.py3-none-any.whl
pip install ./importlib_metadata-2.1.3-py2.py3-none-any.whl
pip install ./distlib-0.3.6-py2.py3-none-any.whl
pip install platformdirs-2.0.2-py2.py3-none-any.whl
pip install ./filelock-3.2.1-py2.py3-none-any.whl
pip install ./singledispatch-3.7.0-py2.py3-none-any.whl
pip install ./importlib_resources-3.3.1-py2.py3-none-any.whl
pip install ./virtualenv-20.15.1-py2.py3-none-any.whl

가상환경 생성 
python -m virtualenv virtualDirectory

반응형
반응형

NULL값 insert 시 발생한 오류.

"varbinary은(는) text과(와) 호환되지 않습니다."

 

내 테이블의 컬럼은 null이 가능한 컬럼인데..?

 

NULL이 binary 형태의 값으로 변환되어 들어가려고 해서 오류가 남..

해결 : NULL이 아니라 ''  즉 공백으로 넣으니 들어간다.... 거참

 

반응형
반응형

파일 확장자를 바꾸고 업로드 하는 경우 파일타입을 체크하기 위해 MIME타입 확인이 필요하게 되었다.

tika 라이브러리를 사용하였다.

MimeTypesFileTypeMap도 사용해봤는데 application/octet-stream만 반환해서 집어치웠음.

* 개발환경 : java7

* pom.xml에 의존성추가

<dependency>
<groupId>org.apache.tika</groupId>
<artifactId>tika-core</artifactId>
<version>1.17</version>
</dependency>

 

Tika 객체를 생성해서 detect 메소드 사용

Tika tika = new Tika();
File file = new File("d:\\example\\file.txt")
String type = tika.detect(file);
System.out.println("type : " + type);

이미지 파일로 테스트 해 본 결과 아래와 같은 type들을 반환해주었다.

image/bmp
image/jpeg
image/png

반응형
반응형

TIKA 라이브러리 사용시 발생한 에러 

java.lang.UnsupportedClassVersionError: org/apache/tika/Tika : Unsupported major.minor version 52.0

 

* 개발환경 : JAVA 7

* 문제점

java7 환경에서는 tika 버전을 최대 1.17까지밖에 못쓴다.

그 이후의 릴리즈는 최소 java 8이 필요함 

 

* 아래 내용 참고 

13 December 2017: Apache Tika ReleaseApache Tika 1.17 has been released! This release includes new support for automatic image captioning, as well as numerous bug fixes and upgrades to dependencies. PLEASE NOTE: this will be the last version that will support Java 7. The next versions will require Java 8. Please see the CHANGES.txt file for the full list of changes in the release and have a look at the download page for more information on how to obtain Apache Tika 1.17.

https://tika.apache.org/

 

Apache Tika – Apache Tika

Apache Tika - a content analysis toolkit The Apache Tika™ toolkit detects and extracts metadata and text from over a thousand different file types (such as PPT, XLS, and PDF). All of these file types can be parsed through a single interface, making Tika

tika.apache.org

 

반응형

+ Recent posts