이렇게 하면 file이 업로드 되었을때, 이벤트도 받을 수 있다.

 

<dependency>
    <groupId>org.apache.ftpserver</groupId>
    <artifactId>ftpserver-core</artifactId>
    <version>1.1.1</version>
</dependency>

 

import org.apache.ftpserver.FtpServer;
import org.apache.ftpserver.FtpServerFactory;
import org.apache.ftpserver.ftplet.Ftplet;
import org.apache.ftpserver.ftplet.FtpletContext;
import org.apache.ftpserver.ftplet.FtpletResult;
import org.apache.ftpserver.ftplet.FtpException;
import org.apache.ftpserver.listener.ListenerFactory;
import org.apache.ftpserver.usermanager.PropertiesUserManagerFactory;
import org.apache.ftpserver.usermanager.SaltedPasswordEncryptor;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import java.io.File;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

@Component
public class EmbeddedFtpServer {

    @PostConstruct
    public void startFtpServer() {
        FtpServerFactory serverFactory = new FtpServerFactory();
        ListenerFactory factory = new ListenerFactory();
        
        // Set the port of the listener
        factory.setPort(2221);
        serverFactory.addListener("default", factory.createListener());

        // Setup user manager
        PropertiesUserManagerFactory userManagerFactory = new PropertiesUserManagerFactory();
        userManagerFactory.setFile(new File("users.properties"));
        userManagerFactory.setPasswordEncryptor(new SaltedPasswordEncryptor());
        serverFactory.setUserManager(userManagerFactory.createUserManager());

        // Add Ftplet to handle FTP events
        Map<String, Ftplet> ftplets = new HashMap<>();
        ftplets.put("eventListenerFtplet", new EventListenerFtplet());
        serverFactory.setFtplets(ftplets);

        // Start the server
        FtpServer server = serverFactory.createServer();
        try {
            server.start();
            System.out.println("Embedded FTP server started.");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

 

이벤트 수신

import org.apache.ftpserver.ftplet.*;

import java.io.IOException;

public class EventListenerFtplet extends DefaultFtplet {

    @Override
    public FtpletResult onUploadStart(FtpSession session, FtpRequest request) throws FtpException, IOException {
        System.out.println("Start uploading file: " + request.getArgument());
        return FtpletResult.DEFAULT;
    }

    @Override
    public FtpletResult onUploadEnd(FtpSession session, FtpRequest request) throws FtpException, IOException {
        System.out.println("Finished uploading file: " + request.getArgument());
        return FtpletResult.DEFAULT;
    }

    @Override
    public FtpletResult onConnect(FtpSession session) throws FtpException, IOException {
        System.out.println("User connected: " + session.getUser().getName());
        return FtpletResult.DEFAULT;
    }

    @Override
    public FtpletResult onDisconnect(FtpSession session) throws FtpException, IOException {
        System.out.println("User disconnected: " + session.getUser().getName());
        return FtpletResult.DEFAULT;
    }
}

 

사용자까지 설정한 예제는:

import org.apache.ftpserver.FtpServerFactory;
import org.apache.ftpserver.listener.ListenerFactory;
import org.apache.ftpserver.usermanager.PropertiesUserManagerFactory;
import org.apache.ftpserver.usermanager.impl.BaseUser;
import org.apache.ftpserver.usermanager.impl.SaltedPasswordEncryptor;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import java.io.File;

@Component
public class EmbeddedFtpServer {

    @PostConstruct
    public void startFtpServer() {
        FtpServerFactory serverFactory = new FtpServerFactory();
        ListenerFactory factory = new ListenerFactory();
        
        // Set the port of the listener
        factory.setPort(2221);
        serverFactory.addListener("default", factory.createListener());

        // Setup user manager
        PropertiesUserManagerFactory userManagerFactory = new PropertiesUserManagerFactory();
        userManagerFactory.setPasswordEncryptor(new SaltedPasswordEncryptor());
        var userManager = userManagerFactory.createUserManager();

        // Create a new user
        BaseUser user = new BaseUser();
        user.setName("user1");
        user.setPassword("pass1");
        user.setHomeDirectory("/path/to/root/folder1");
        user.setEnabled(true);

        // Set permissions if needed (e.g., write permission)
        userManager.save(user);

        serverFactory.setUserManager(userManager);

        // Start the server
        FtpServer server = serverFactory.createServer();
        try {
            server.start();
            System.out.println("Embedded FTP server started.");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
Posted by yongary
,

Entity class에 @Document 어노테이션을 추가하고,

특정필드에 @Indexed를 추가하면 자동으로 인덱스가 생성된다.

만약에 잘 안되면, 원인분석을 해야겠지만,

임시로 코드로 하는 방법이있는데, 다음과 같다.

1.  잘 동작함 - MongoConfig 수정 방식

    //AUTO INDEX CREATION안되서 추가: 참고- https://github.com/spring-projects/spring-boot/issues/28478#issuecomment-954627106
    @Override
    protected boolean autoIndexCreation() {
        return true;
    }

    @Bean
    @Primary
    public MongoMappingContext mongoMappingContext(MongoCustomConversions conversions, MongoManagedTypes managedTypes) {
        MongoMappingContext mappingContext = super.mongoMappingContext(conversions, managedTypes);
        mappingContext.setAutoIndexCreation(true);
        return mappingContext;
    }



 

 

 

2. not TESTED. - post Construct방식

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.index.Index;
import org.springframework.data.mongodb.core.index.IndexOperations;
import org.springframework.stereotype.Service;

import javax.annotation.PostConstruct;

@Service
public class IndexCreatorService {

    @Autowired
    private MongoTemplate mongoTemplate;

    @PostConstruct
    public void initIndexes() {
        IndexOperations indexOps = mongoTemplate.indexOps(ExampleEntity.class);
        indexOps.ensureIndex(new Index().on("fieldToIndex", org.springframework.data.domain.Sort.Direction.ASC));
    }
}
Posted by yongary
,

 

1. 스왑 파일 생성

먼저, 원하는 크기의 스왑 파일을 생성합니다. 여기서는 2GB 크기의 스왑 파일을 예로 들겠습니다.

bash
코드 복사
sudo fallocate -l 4G /swapfile

만약 fallocate 명령이 지원되지 않는 경우, dd 명령을 사용할 수도 있습니다:

bash
코드 복사
sudo dd if=/dev/zero of=/swapfile bs=1M count=4096

2. 스왑 파일에 적절한 권한 설정

스왑 파일에 올바른 권한을 설정하여 루트 사용자만 접근할 수 있도록 합니다.

bash
코드 복사
sudo chmod 600 /swapfile

3. 스왑 파일 형식 지정

스왑 파일을 스왑 공간으로 초기화합니다.

bash
코드 복사
sudo mkswap /swapfile

4. 스왑 파일 활성화

스왑 파일을 활성화하여 사용합니다.

bash
코드 복사
sudo swapon /swapfile

5. 스왑 공간 확인

스왑 공간이 제대로 활성화되었는지 확인합니다.

bash
코드 복사
sudo swapon --show

또는:

bash
코드 복사
free -h

6. 스왑 파일을 영구적으로 추가

재부팅 후에도 스왑 파일이 자동으로 활성화되도록 /etc/fstab 파일에 항목을 추가합니다.

bash
코드 복사
echo '/swapfile none swap sw 0 0' | sudo tee -a /etc/fstab
Posted by yongary
,

 

spreadJs의 디자이너를 통해 .sjs파일을 만들어 포매팅에 이용할 수 있다.

import React, { useEffect, useRef, useState } from 'react';
import Head from 'next/head';
import GC from '@mescius/spread-sheets'; // 또는 '@grapecity/spread-sheets'
import '@mescius/spread-sheets-resources-ko';
import '@mescius/spread-sheets/styles/gc.spread.sheets.excel2013white.css';

const HomePage = () => {
  const containerRef = useRef(null);
  const [spread, setSpread] = useState(null);

  useEffect(() => {
    if (containerRef.current && !spread) {
      const newSpread = new GC.Spread.Sheets.Workbook(containerRef.current, { sheetCount: 1 });
      setSpread(newSpread);
      console.log('Spread initialized:', newSpread);

      // .sjs 파일 로드
      fetch('/data/spreadsheet.sjs')
        .then(response => response.json())
        .then(json => {
          newSpread.fromJSON(json);
          console.log('Spread loaded from .sjs file:', json);
        })
        .catch(error => console.error('Error loading .sjs file:', error));
    }
  }, [containerRef, spread]);

  useEffect(() => {
    return () => {
      if (spread) {
        spread.destroy();
      }
    };
  }, [spread]);

  return (
    <div>
      <Head>
        <link rel="stylesheet" href="/scripts/gc.spread.sheets.17.0.7.css" />
      </Head>
      <h1>SpreadJS Example</h1>
      <div ref={containerRef} className="spreadContainer" style={{ top: '240px', bottom: '10px', position: 'relative', height: '500px' }}>
        {/* SpreadJS 워크북이 여기에 표시됩니다 */}
      </div>
    </div>
  );
};

export default HomePage;
Posted by yongary
,