Notice
Recent Posts
Recent Comments
Link
투케이2K
148. (TWOK/UTIL) [Ios/Swift] C_FTP_NWConnection_Client_Module : FTP 파일 업로드 및 다운로드 , 사용자 인증 유틸 본문
투케이2K 유틸파일
148. (TWOK/UTIL) [Ios/Swift] C_FTP_NWConnection_Client_Module : FTP 파일 업로드 및 다운로드 , 사용자 인증 유틸
투케이2K 2024. 12. 6. 18:49[설 명]
프로그램 : Ios / Swift
설 명 : C_FTP_NWConnection_Client_Module : FTP 파일 업로드 및 다운로드 , 사용자 인증 유틸
[소스 코드]
import Foundation
import UIKit
// -----------------------------------------
//MARK: [네트워크 소켓 통신 사용]
import Network
// -----------------------------------------
class C_FTP_NWConnection_Client_Module {
/**
* // -----------------------------------------------------------------------------------------------------------------------------------------------------------------
* TODO [클래스 설명]
* // -----------------------------------------------------------------------------------------------------------------------------------------------------------------
* 1. NWConnection FTP 연결 및 파일 업로드, 다운로드 관련 클래스
* // -----------------------------------------------------------------------------------------------------------------------------------------------------------------
* 2. NWConnection : ios 12 이상 부터 사용 가능한 애플에서 지원하는 네트워크 프레임 워크입니다
* // -----------------------------------------------------------------------------------------------------------------------------------------------------------------
* 3. NWConnection 는 로컬 엔드포인트와 원격 엔드포인트 간의 양방향 데이터 연결 (TCP , UDP) 을 수행할 수 있습니다
* // -----------------------------------------------------------------------------------------------------------------------------------------------------------------
* 4. NWConnection 를 사용하기 위해서는 import Network 패키지 호출 정의가 필요합니다
* // -----------------------------------------------------------------------------------------------------------------------------------------------------------------
* 5. NWParameters 설정 가능 옵션 : tls , tcp , dtls , udp , quic , quicDatagram
* // -----------------------------------------------------------------------------------------------------------------------------------------------------------------
* 6. 애플 공식 참고 사이트 : https://developer.apple.com/documentation/network/nwconnection
* // -----------------------------------------------------------------------------------------------------------------------------------------------------------------
* */
/**
* // -----------------------------------------------------------------------------------------------------------------------------------------------------------------
* TODO [빠른 로직 찾기 : 주석 로직 찾기]
* // -----------------------------------------------------------------------------------------------------------------------------------------------------------------
* [SEARCH FAST] : observableFtpConnect : FTP 연결 수행
* // -----------------------------------------------------------------------------------------------------------------------------------------------------------------
* [SEARCH FAST] : closeFtpConnect : FTP 연결 종료 수행
* // -----------------------------------------------------------------------------------------------------------------------------------------------------------------
* [SEARCH FAST] : receiveData : 실시간 메시지 수신 상태 확인
* // -----------------------------------------------------------------------------------------------------------------------------------------------------------------
* [SEARCH FAST] : observableUserAuth : FTP 사용자 ID 인증 요청 상태 확인
* // -----------------------------------------------------------------------------------------------------------------------------------------------------------------
* [SEARCH FAST] : observablePwAuth : FTP 사용자 PW 인증 요청 상태 확인
* // -----------------------------------------------------------------------------------------------------------------------------------------------------------------
* [SEARCH FAST] : loginCallbackReturn : FTP 로그인 콜백 처리 수행
* // -----------------------------------------------------------------------------------------------------------------------------------------------------------------
* [SEARCH FAST] : observableUploadFile : 실시간 파일 업로드 수행
* // -----------------------------------------------------------------------------------------------------------------------------------------------------------------
* [SEARCH FAST] : observableDownloadFile : 실시간 파일 다운로드 수행
* // -----------------------------------------------------------------------------------------------------------------------------------------------------------------
* [SEARCH FAST] : observablePassiveMode : 파일 다운로드 패시브 모드 수행
* // -----------------------------------------------------------------------------------------------------------------------------------------------------------------
* [SEARCH FAST] : observableNewDownloadConnection : 파일 다운로드 NEW 새로운 접속 수행
* // -----------------------------------------------------------------------------------------------------------------------------------------------------------------
* [SEARCH FAST] : receiveFile : 실시간 파일 다운로드 수신 상태 확인
* // -----------------------------------------------------------------------------------------------------------------------------------------------------------------
* [SEARCH FAST] : downloadCallbackReturn : FTP 파일 다운로드 콜백 처리 수행
* // -----------------------------------------------------------------------------------------------------------------------------------------------------------------
*
* // -----------------------------------------------------------------------------------------------------------------------------------------------------------------
*/
/**
* // -----------------------------------------------------------------------------------------------------------------------------------------------------------------
* TODO [소스 코드 사용 방법]
* // -----------------------------------------------------------------------------------------------------------------------------------------------------------------
DispatchQueue.main.async { // [비동기 요청]
// [FTP 접속을 위한 변수 선언]
let server = "twok2k.dothome.co.kr"
let port = 21 // [FTP 는 21 번 포트]
let userName = "twok2k"
let pw = "twok00$$admin"
// -----------------------------------------
// [FTP 연결 요청 수행]
// -----------------------------------------
// 1. 사용자 FPT 서버 활성 접속 상태 확인
// -----------------------------------------
// 2. USER 커맨드를 사용해 사용자 ID 인증 요청
// -----------------------------------------
// 3. PASS 커맨드를 사용해 사용자 PW 인증 요청
// -----------------------------------------
C_FTP_NWConnection_Client_Module().observableFtpConnect(server: server, port: UInt16(port), userName: userName, pw: pw){(connectResult) in
S_Log._F_(description: "FTP 연결 확인 수행", data: ["\(connectResult)"])
if connectResult == true {
// -----------------------------------------
// [FTP 파일 업로드 로직]
// -----------------------------------------
// 1. STOR 커맨드 사용해 파일 업로드 상태 전환
// -----------------------------------------
// 2. 앱 내부 로컬에 저장 된 파일 send 보내기 수행
// -----------------------------------------
/*
DispatchQueue.main.asyncAfter(deadline: .now() + 5) { // [5초 시간 설정]
let fileUrl = C_App().get_File_Url(folderName: "LOG_FILE_FOLDER", fileName: "APP_CRASH_LOG_FILE.txt")
S_Log._F_(description: "FTP 파일 송수신 URL 확인", data: ["\(String(describing: fileUrl))"])
C_FTP_NWConnection_Client_Module().observableUploadFile(fileUrl: fileUrl?.description ?? "", remoteUrl:"/html/crash.txt"){(sendResult) in
S_Log._F_(description: "FTP 실시간 파일 전송 확인", data: ["\(sendResult)"])
if sendResult == true {
}
else {
S_Log._F_(description: "FTP 실시간 파일 전송 에러 메시지", data: ["\(C_FTP_NWConnection_Client_Module.UPLOAD_ERROR_LOG)"])
}
}
}
// */
// -----------------------------------------
// [FTP 파일 다운로드 로직]
// -----------------------------------------
// 1. TYPE 커맨드 사용해 바이너리 업로드 상태 전환
// -----------------------------------------
// 2. PASV 커맨드 사용해 패시브 모드 상태 전환
// -----------------------------------------
// 3. 성공적으로 패시브 모드 전환 시 새롭게 내려온 NEW 서버 주소 파싱 수행 : Entering Passive Mode (112,175,185,132,198,97)
// -----------------------------------------
// 4. NWConnection 새롭게 생성 후 ready 상태로 진입 수행
// -----------------------------------------
// 5. PASV 커맨드 사용해 로그인 한 커넥션 객체로 send 메시지 전송 (파일 내려 주세요. 요청)
// -----------------------------------------
// 6. 신규 NWConnection 객체 reciveFile 리시버에서 파일 다운로드가 응답 되면 앱 내부에 파일 저장 수행
// -----------------------------------------
/*
DispatchQueue.main.asyncAfter(deadline: .now() + 5) { // [5초 시간 설정]
C_FTP_NWConnection_Client_Module().observableDownloadFile(remoteUrl: "/html/crash.txt", localFileName:"crash.txt"){(sendResult) in
S_Log._F_(description: "FTP 실시간 파일 다운로드 확인", data: ["\(sendResult)"])
if sendResult == true {
}
else {
S_Log._F_(description: "FTP 실시간 파일 다운로드 에러 메시지", data: ["\(C_FTP_NWConnection_Client_Module.DOWNLOAD_ERROR_LOG)"])
}
}
}
// */
}
else {
S_Log._F_(description: "FTP 연결 에러 메시지", data: ["\(C_FTP_NWConnection_Client_Module.FTP_CONNECT_LOG)"])
}
}
}
* // -----------------------------------------------------------------------------------------------------------------------------------------------------------------
* */
// -----------------------------------------------------------------------------------------
// MARK: - [전역 변수 선언]
// -----------------------------------------------------------------------------------------
private static let ACTIVITY_NAME = "C_FTP_NWConnection_Client_Module"
let CONNECT_TIME_OUT = 20.0 // [연결 타임 아웃 시간]
lazy var tcpOptions: NWProtocolTCP.Options = {
let options = NWProtocolTCP.Options()
options.noDelay = true // [딜레이 비활성]
options.connectionTimeout = Int(self.CONNECT_TIME_OUT) // [connection timed out]
return options
}()
lazy var parames: NWParameters = {
let parames = NWParameters(tls: nil, tcp: self.tcpOptions)
if let isOption = parames.defaultProtocolStack.internetProtocol as? NWProtocolIP.Options {
//isOption.version = .v4 // [ipv4 방식 : 192.168.1.1]
}
parames.preferNoProxies = true
return parames
}()
static var connection: NWConnection? = nil // [FTP 통신 수행 객체]
var workItem: DispatchWorkItem? = nil // [연결 타임 아웃 핸들러]
static var fileNwconnection: NWConnection? = nil // [파일 다운로드 통신 객체]
static var connectFlag = false // MARK: [FTP 연결 및 로그인 수행 완료 플래그 값]
static var downloadFlag = false // MARK: [FTP 파일 다운로드 완료 플래그 값]
static var FTP_SERTVER = "" // [지속 사용]
static var FTP_PORT = 0 // [지속 사용]
static var FTP_USER_NAME = "" // [지속 사용]
static var FTP_USER_PW = "" // [지속 사용]
// -----------------------------------------------------------------------------------------
// MARK: - [SEARCH FAST] : observableFtpConnect : FTP 연결 수행
// -----------------------------------------------------------------------------------------
// 1. 사용자 FPT 서버 활성 접속 상태 확인
// -----------------------------------------------------------------------------------------
// 2. USER 커맨드를 사용해 사용자 ID 인증 요청
// -----------------------------------------------------------------------------------------
// 3. PASS 커맨드를 사용해 사용자 PW 인증 요청
// -----------------------------------------------------------------------------------------
static var FTP_CONNECT_LOG = ""
static var connectOperationQueue = OperationQueue()
func observableFtpConnect(server: String, port: UInt16, userName: String, pw: String, completion: @escaping (Bool)->()) {
/*
// -----------------------------------------
[observableFtpConnect 메소드 설명]
// -----------------------------------------
1. 도메인, 사용자 정보 사용해 FTP 연결 수행
// -----------------------------------------
2. 호출 방법 : MARK: [FTP 포트는 21 번 포트]
C_FTP_NWConnection_Client_Module().observableFtpConnect(server: "towk.test.co.kr", port: UInt16(21), userName: "twok123", pw: "twok0123456789"){(connectResult) in
S_Log._F_(description: "FTP 연결 확인 수행", data: ["\(connectResult)"])
if connectResult == true {
// [FTP 연결 완료 로직 처리]
}
else {
S_Log._F_(description: "FTP 연결 에러 메시지", data: ["\(C_FTP_NWConnection_Client_Module.FTP_CONNECT_LOG)"])
}
}
// -----------------------------------------
3. 필요 import :
import Network
// -----------------------------------------
*/
// [변수 선언 및 초기화]
C_FTP_NWConnection_Client_Module.connection = nil
C_FTP_NWConnection_Client_Module.FTP_CONNECT_LOG = ""
self.workItem = nil
C_FTP_NWConnection_Client_Module.connectFlag = false // MARK: [최종 서버 접속 및 로그인 성공 플래그 처리 변수]
C_FTP_NWConnection_Client_Module.FTP_SERTVER = ""
C_FTP_NWConnection_Client_Module.FTP_PORT = 0
C_FTP_NWConnection_Client_Module.FTP_USER_NAME = ""
C_FTP_NWConnection_Client_Module.FTP_USER_PW = ""
// MARK: [작업 큐에 추가]
C_FTP_NWConnection_Client_Module.connectOperationQueue.isSuspended = true
let block = { completion(C_FTP_NWConnection_Client_Module.connectFlag) }
C_FTP_NWConnection_Client_Module.connectOperationQueue.addOperation(block)
// [로직 처리 수행]
DispatchQueue.main.async {
S_Log._D_(description: "FTP 연결 수행", data: [ "SERVER :: \(server)", "PORT :: \(port)", "USER_NAME :: \(userName)", "PW :: \(pw)" ])
// [인풋 데이터 널 체크]
if C_Util().stringNotNull(str: server) == true && port >= 0
&& C_Util().stringNotNull(str: userName) == true && C_Util().stringNotNull(str: pw) == true {
// ---------------------------------------------
// MARK: [전역 변수 지정 수행]
// ---------------------------------------------
var loginUrl = ""
C_FTP_NWConnection_Client_Module.FTP_SERTVER = server
C_FTP_NWConnection_Client_Module.FTP_PORT = Int(port)
//C_FTP_NWConnection_Client_Module.FTP_USER_NAME = userName.addingPercentEncoding(withAllowedCharacters: .urlUserAllowed) ?? ""
//C_FTP_NWConnection_Client_Module.FTP_USER_PW = pw.addingPercentEncoding(withAllowedCharacters: .urlPasswordAllowed) ?? ""
C_FTP_NWConnection_Client_Module.FTP_USER_NAME = userName
C_FTP_NWConnection_Client_Module.FTP_USER_PW = pw
// ---------------------------------------------
// MARK: [FTP 접속 URL 형식 지정 및 연결 요청 수행]
// ---------------------------------------------
// MARK: ftp://username:password@ftp.example.com:21
// ---------------------------------------------
loginUrl = "ftp://\(userName.addingPercentEncoding(withAllowedCharacters: .urlUserAllowed) ?? ""):\(pw.addingPercentEncoding(withAllowedCharacters: .urlPasswordAllowed) ?? "")@\(server):\(port)"
// [FTP 연결 옵션 지정]
C_FTP_NWConnection_Client_Module.connection = NWConnection(to: .url(URL(string: loginUrl)!), using: self.parames)
// [연결 상태 업데이트 핸들러 설정]
C_FTP_NWConnection_Client_Module.connection?.stateUpdateHandler = { state in
switch state {
case .ready:
C_FTP_NWConnection_Client_Module.FTP_CONNECT_LOG = "[Success] : Connection Ready State"
S_Log._W_(description: "FTP 연결 성공", data: [
"M_LOG :: \(C_FTP_NWConnection_Client_Module.FTP_CONNECT_LOG)",
"loginUrl :: \(loginUrl)"
])
// ---------------------------------------------
// MARK: [실시간 메시지 수신 상태 확인]
// ---------------------------------------------
// MARK: [receiveData 에서 사용자 로그인 처리 까지 완료 후 콜백 반환 수행]
// ---------------------------------------------
self.receiveData()
case .failed(let error):
C_FTP_NWConnection_Client_Module.FTP_CONNECT_LOG = "[Fail] : Connection Fail State"
S_Log._E_(description: "FTP 연결 실패", data: [
"M_LOG :: \(C_FTP_NWConnection_Client_Module.FTP_CONNECT_LOG)",
"Description :: \(error)"
])
// [콜백 반환]
if C_FTP_NWConnection_Client_Module.connectFlag == false {
C_FTP_NWConnection_Client_Module.connectOperationQueue.isSuspended = false
}
// [객체 초기화]
if C_FTP_NWConnection_Client_Module.connection != nil {
C_FTP_NWConnection_Client_Module.connection = nil
C_FTP_NWConnection_Client_Module.connectFlag = false
}
return
case .cancelled:
C_FTP_NWConnection_Client_Module.FTP_CONNECT_LOG = "[Cancel] : Connection Cancel State"
S_Log._E_(description: "FTP 연결 실패", data: [
"M_LOG :: \(C_FTP_NWConnection_Client_Module.FTP_CONNECT_LOG)"
])
// [콜백 반환]
if C_FTP_NWConnection_Client_Module.connectFlag == false {
C_FTP_NWConnection_Client_Module.connectOperationQueue.isSuspended = false
}
// [객체 초기화]
if C_FTP_NWConnection_Client_Module.connection != nil {
C_FTP_NWConnection_Client_Module.connection = nil
C_FTP_NWConnection_Client_Module.connectFlag = false
}
return
default:
break
}
}
// [연결 시작]
C_FTP_NWConnection_Client_Module.connection?.start(queue: .global())
// ---------------------------------------------
// MARK: [FTP 연결 타임 아웃 처리]
// ---------------------------------------------
self.workItem = DispatchWorkItem {
if C_FTP_NWConnection_Client_Module.connection != nil && C_FTP_NWConnection_Client_Module.connectFlag == false {
C_FTP_NWConnection_Client_Module.FTP_CONNECT_LOG = "[Time Out] : FTP Connection TimeOut"
S_Log._E_(description: "FTP 연결 실패", data: [
"M_LOG :: \(C_FTP_NWConnection_Client_Module.FTP_CONNECT_LOG)"
])
// [FTP 연결 취소]
C_FTP_NWConnection_Client_Module.connection?.cancel()
}
}
let delay = DispatchTime.now() + self.CONNECT_TIME_OUT // [특정 시간 후에 실행]
DispatchQueue.main.asyncAfter(deadline: delay, execute: self.workItem!)
}
else {
C_FTP_NWConnection_Client_Module.FTP_CONNECT_LOG = "[Error] : Input Data Is Null"
S_Log._E_(description: "FTP 연결 에러", data: [
"M_LOG :: \(C_FTP_NWConnection_Client_Module.FTP_CONNECT_LOG)"
])
// [콜백 반환]
C_FTP_NWConnection_Client_Module.connectOperationQueue.isSuspended = false
return
}
}
}
// -----------------------------------------------------------------------------------------
// MARK: - [SEARCH FAST] : closeFtpConnect : FTP 연결 종료 수행
// -----------------------------------------------------------------------------------------
func closeFtpConnect() {
if C_FTP_NWConnection_Client_Module.connection != nil {
S_Log._E_(description: "FTP 연결 종료 수행 [IF]", data: nil)
C_FTP_NWConnection_Client_Module.connection?.cancel()
C_FTP_NWConnection_Client_Module.connection = nil
C_FTP_NWConnection_Client_Module.connectFlag = false
}
else {
S_Log._E_(description: "FTP 연결 종료 수행 [ELSE]", data: nil)
}
}
// -----------------------------------------------------------------------------------------
// MARK: - [SEARCH FAST] : receiveData : 실시간 메시지 수신 상태 확인
// -----------------------------------------------------------------------------------------
static var RECEIVE_ERROR_LOG = ""
private func receiveData() {
if C_FTP_NWConnection_Client_Module.connection != nil {
S_Log._D_(description: "RECEIVE 실시간 메시지 수신 감지 수행", data: nil)
C_FTP_NWConnection_Client_Module.connection?.receive(minimumIncompleteLength: 1, maximumLength: 1024, completion: { data, _, isComplete, error in
// -----------------------------------------------------------------------
// MARK: [실시간 메시지 수신 확인]
// -----------------------------------------------------------------------
if let data = data, !data.isEmpty {
let message = String(data: data, encoding: .utf8) ?? ""
S_Log._D_(description: "[Ing] ---- [RECEIVE 실시간 메시지 수신 감지] ---- [Ing]", data: [
"message :: \(message)"
])
// ---------------------------------------------
// MARK: [220] : [로직 분기 처리] : FTP 서버 준비 완료 상태
// ---------------------------------------------
if message.trim().startsWith(_string: "220") == true {
// MARK: [220 FTP Server ready.]
S_Log._W_(description: "FTP 서버 준비 완료 상태 확인", data: [
"message :: \(message)"
])
// MARK: [FTP 로그인 사용자 인증 수행 실시]
C_FTP_NWConnection_Client_Module().observableUserAuth(){(sendResult) in
S_Log._D_(description: "FTP 로그인 사용자 ID 인증 수행 확인", data: ["\(sendResult)"])
if sendResult == true {
}
else {
S_Log._E_(description: "FTP 로그인 사용자 ID 인증 수행 에러 메시지", data: ["\(C_FTP_NWConnection_Client_Module.LOGIN_USER_ERROR_LOG)"])
// [로그인 실패 콜백 처리]
self.loginCallbackReturn(returnValue: false)
}
}
}
// ---------------------------------------------
// MARK: [331] : [로직 분기 처리] : 사용자의 암호를 입력 하십시오
// ---------------------------------------------
if message.trim().startsWith(_string: "331") == true {
// MARK: [331 사용자의 암호를 입력 하십시오.] : 사용자 ID 인증 성공
S_Log._W_(description: "FTP 서버 사용자 인증 완료 상태 확인", data: [
"message :: \(message)"
])
// MARK: [FTP 로그인 사용자 PW 확인 실시]
C_FTP_NWConnection_Client_Module().observablePwAuth(){(sendResult) in
S_Log._D_(description: "FTP 로그인 사용자 PW 인증 수행 확인", data: ["\(sendResult)"])
if sendResult == true {
}
else {
S_Log._E_(description: "FTP 로그인 사용자 PW 인증 수행 에러 메시지", data: ["\(C_FTP_NWConnection_Client_Module.LOGIN_PW_ERROR_LOG)"])
// [로그인 실패 콜백 처리]
self.loginCallbackReturn(returnValue: false)
}
}
}
// ---------------------------------------------
// MARK: [530] : [로직 분기 처리] : 로그인에 실패했습니다
// ---------------------------------------------
if message.trim().startsWith(_string: "530") == true {
// MARK: [530 로그인에 실패했습니다.] : 변수 초기화
S_Log._E_(description: "FTP 서버 ID, PW 인증 실패 상태 확인", data: [
"message :: \(message)"
])
// [로그인 실패 콜백 처리]
self.loginCallbackReturn(returnValue: false)
}
// ---------------------------------------------
// MARK: [230] : [로직 분기 처리] : 사용자 로그인 성공
// ---------------------------------------------
if message.trim().startsWith(_string: "230") == true {
// MARK: [230 사용자 로그인] : 변수 초기화
S_Log._W_(description: "FTP 서버 ID, PW 인증 성공 상태 확인", data: [
"message :: \(message)"
])
// [로그인 성공 콜백 처리]
self.loginCallbackReturn(returnValue: true)
}
// ---------------------------------------------
// MARK: [200] I Type 설정 : 바이너리 모드 설정
// ---------------------------------------------
if message.trim().startsWith(_string: "200") == true {
// MARK: [200 I Type 설정]
S_Log._W_(description: "FTP Type 바이너리 모드 설정 확인", data: [
"message :: \(message)"
])
// MARK: [FTP 파일 다운로드 패시브 모드 설정]
C_FTP_NWConnection_Client_Module().observablePassiveMode(){(sendResult) in
S_Log._D_(description: "FTP 파일 다운로드 패시브 모드 확인", data: ["\(sendResult)"])
if sendResult == true {
}
else {
S_Log._E_(description: "FTP 파일 다운로드 패시브 모드 에러 메시지", data: ["\(C_FTP_NWConnection_Client_Module.DOWNLOAD_ERROR_LOG)"])
// [파일 다운로드 실패 콜백 처리]
self.downloadCallbackReturn(returnValue: false)
}
}
}
// ---------------------------------------------
// MARK: [227] : [로직 분기 처리] : Entering Passive Mode 패시브 모드 진입
// ---------------------------------------------
// MARK: 227 Entering Passive Mode (112,175,185,132,198,97).
// ---------------------------------------------
if message.trim().startsWith(_string: "227") == true {
// MARK: [227 Entering Passive Mode 패시브 모드 진입]
S_Log._W_(description: "FTP Entering Passive Mode 패시브 모드 진입 확인", data: [
"message :: \(message)"
])
// MARK: [FTP 파일 다운로드를 수행하기 위한 정규식 사용 데이터 파싱 수행]
let regex = try! NSRegularExpression(pattern: "\\((.*?)\\)")
if let match = regex.firstMatch(in: message, range: NSRange(location: 0, length: message.count)) {
let params = (message as NSString).substring(with: match.range(at: 1)).split(separator: ",")
if params.count == 6 {
let host = "\(params[0]).\(params[1]).\(params[2]).\(params[3])"
let port = (UInt16(params[4])! << 8) + UInt16(params[5])!
S_Log._D_(description: "FTP 파일 다운로드를 위한 NEW 접속 정보 확인", data: [
"host :: \(host)",
"port :: \(port)"
])
C_FTP_NWConnection_Client_Module().observableNewDownloadConnection(server: host, port: port){(connectResult) in
S_Log._D_(description: "NEW 파일 서버 연결 확인 수행", data: ["\(connectResult)"])
if connectResult == true {
}
else {
S_Log._E_(description: "NEW 파일 서버 연결 에러 메시지", data: ["\(C_FTP_NWConnection_Client_Module.NEW_CONNECT_LOG)"])
// [파일 다운로드 실패 콜백 처리]
self.downloadCallbackReturn(returnValue: false)
}
}
}
}
else {
C_FTP_NWConnection_Client_Module.DOWNLOAD_ERROR_LOG = "[Error] : FTP File Download Ural Parse Error"
S_Log._E_(description: "FTP 파일 다운로드 에러", data: [
"M_LOG :: \(C_FTP_NWConnection_Client_Module.DOWNLOAD_ERROR_LOG)"
])
// [파일 다운로드 실패 콜백 처리]
self.downloadCallbackReturn(returnValue: false)
}
}
// ---------------------------------------------
// MARK: [150] : [로직 분기 처리] : BINARY 모드로 데이터 연결 열기
// ---------------------------------------------
if message.trim().startsWith(_string: "150") == true {
// MARK: [150 RETR 설정]
S_Log._W_(description: "FTP RETR 모드 설정 확인", data: [
"message :: \(message)"
])
// MARK: [self.receiveFile() :: 실시간 파일 다운로드 리시버에서 파일 등록 처리]
}
// ---------------------------------------------
// MARK: [226] : [로직 분기 처리] : 전송 완료 : 파일 다운로드
// ---------------------------------------------
if message.trim().startsWith(_string: "226") == true {
// MARK: [226 전송 완료]
S_Log._W_(description: "FTP 파일 다운로드 전송 완료", data: [
"message :: \(message)"
])
}
// ---------------------------------------------
// MARK: [550] : 정규 파일이 아님 : 파일 디렉토리를 찾을 수 없음 : No such file or directory
// ---------------------------------------------
// MARK: 원격 서버에 실제 경로가 없거나, 파일 다운로드를 위한 절차를 모두 수행하지 않은 경우 발생
// ---------------------------------------------
/*
*/
// ---------------------------------------------
}
// -----------------------------------------------------------------------
// MARK: [계속해서 실시간 메시지 수신 처리]
// -----------------------------------------------------------------------
if isComplete {
C_FTP_NWConnection_Client_Module.RECEIVE_ERROR_LOG = "[Error] : Connection closed by server"
S_Log._E_(description: "RECEIVE 실시간 메시지 수신 감지 에러", data: [
"M_LOG :: \(C_FTP_NWConnection_Client_Module.RECEIVE_ERROR_LOG)"
])
// ---------------------------------------------
// MARK: [소켓 연결 종료 및 객체 초기화]
// ---------------------------------------------
C_FTP_NWConnection_Client_Module.connection?.cancel()
//C_FTP_NWConnection_Client_Module.connection = nil
//C_FTP_NWConnection_Client_Module.connectFlag = false
} else if let error = error {
C_FTP_NWConnection_Client_Module.RECEIVE_ERROR_LOG = "[Error] : let error catch"
S_Log._E_(description: "RECEIVE 실시간 메시지 수신 감지 에러", data: [
"M_LOG :: \(C_FTP_NWConnection_Client_Module.RECEIVE_ERROR_LOG)",
"Description :: \(error)"
])
// ---------------------------------------------
// MARK: [소켓 연결 종료 및 객체 초기화]
// ---------------------------------------------
C_FTP_NWConnection_Client_Module.connection?.cancel()
//C_FTP_NWConnection_Client_Module.connection = nil
//C_FTP_NWConnection_Client_Module.connectFlag = false
} else {
// ---------------------------------------------
// [계속해서 데이터 수신]
// ---------------------------------------------
self.receiveData()
}
})
}
else {
S_Log._D_(description: "소켓 실시간 메시지 수신 감지 에러 :: connection is null", data: nil)
}
}
// -----------------------------------------------------------------------------------------
// MARK: - [SEARCH FAST] : observableUserAuth : FTP 사용자 ID 인증 요청 상태 확인
// -----------------------------------------------------------------------------------------
static var LOGIN_USER_ERROR_LOG = ""
func observableUserAuth(completion: @escaping (Bool)->()) {
/*
// -----------------------------------------
[observableUserAuth 메소드 설명]
// -----------------------------------------
1. FTP 사용자 ID 인증 요청 상태 확인
// -----------------------------------------
2. 호출 방법 :
C_FTP_NWConnection_Client_Module().observableUserAuth(){(sendResult) in
S_Log._F_(description: "FTP 로그인 사용자 ID 인증 수행 확인", data: ["\(sendResult)"])
if sendResult == true {
}
else {
S_Log._F_(description: "FTP 로그인 사용자 ID 인증 수행 에러 메시지", data: ["\(C_FTP_NWConnection_Client_Module.LOGIN_USER_ERROR_LOG)"])
}
}
// -----------------------------------------
3. 필요 import :
import Network
// -----------------------------------------
*/
// [변수 선언]
C_FTP_NWConnection_Client_Module.LOGIN_USER_ERROR_LOG = ""
// [로직 처리 수행]
DispatchQueue.global().sync {
S_Log._D_(description: "FTP 로그인 사용자 ID 인증 요청 수행", data: nil)
// MARK: [인풋 데이터 널 체크 수행]
if C_FTP_NWConnection_Client_Module.connection != nil
&& C_Util().stringNotNull(str: C_FTP_NWConnection_Client_Module.FTP_USER_NAME) == true
&& C_Util().stringNotNull(str: C_FTP_NWConnection_Client_Module.FTP_USER_PW) == true {
let commandWithCRLF = "USER \(C_FTP_NWConnection_Client_Module.FTP_USER_NAME)" + "\r\n"
C_FTP_NWConnection_Client_Module.connection?.send(content: commandWithCRLF.data(using: .utf8), completion: .contentProcessed { error in
if let error = error {
C_FTP_NWConnection_Client_Module.LOGIN_USER_ERROR_LOG = "[Error] : FTP User Auth Error"
S_Log._E_(description: "FTP 로그인 사용자 ID 인증 에러", data: [
"M_LOG :: \(C_FTP_NWConnection_Client_Module.LOGIN_USER_ERROR_LOG)",
"Description :: \(error)"
])
// [콜백 반환]
completion(false)
return
} else {
S_Log._W_(description: "FTP 로그인 사용자 ID 인증 성공", data: [
"commandWithIdCRLF :: \(commandWithCRLF)"
])
// [콜백 반환]
completion(true)
return
}
})
}
else {
C_FTP_NWConnection_Client_Module.LOGIN_USER_ERROR_LOG = "[Error] : Input Data Is Null"
S_Log._E_(description: "FTP 로그인 사용자 ID 인증 수행 에러", data: [
"M_LOG :: \(C_FTP_NWConnection_Client_Module.LOGIN_USER_ERROR_LOG)"
])
// [콜백 반환]
completion(false)
return
}
}
}
// -----------------------------------------------------------------------------------------
// MARK: - [SEARCH FAST] : observablePwAuth : FTP 사용자 PW 인증 요청 상태 확인
// -----------------------------------------------------------------------------------------
static var LOGIN_PW_ERROR_LOG = ""
func observablePwAuth(completion: @escaping (Bool)->()) {
/*
// -----------------------------------------
[observablePwAuth 메소드 설명]
// -----------------------------------------
1. FTP 사용자 PW 인증 요청 상태 확인
// -----------------------------------------
2. 호출 방법 :
C_FTP_NWConnection_Client_Module().observablePwAuth(){(sendResult) in
S_Log._F_(description: "FTP 로그인 사용자 PW 인증 수행 확인", data: ["\(sendResult)"])
if sendResult == true {
}
else {
S_Log._F_(description: "FTP 로그인 사용자 PW 인증 수행 에러 메시지", data: ["\(C_FTP_NWConnection_Client_Module.LOGIN_PW_ERROR_LOG)"])
}
}
// -----------------------------------------
3. 필요 import :
import Network
// -----------------------------------------
*/
// [변수 선언]
C_FTP_NWConnection_Client_Module.LOGIN_PW_ERROR_LOG = ""
// [로직 처리 수행]
DispatchQueue.global().sync {
S_Log._D_(description: "FTP 로그인 사용자 PW 인증 요청 수행", data: nil)
// MARK: [인풋 데이터 널 체크 수행]
if C_FTP_NWConnection_Client_Module.connection != nil
&& C_Util().stringNotNull(str: C_FTP_NWConnection_Client_Module.FTP_USER_NAME) == true
&& C_Util().stringNotNull(str: C_FTP_NWConnection_Client_Module.FTP_USER_PW) == true {
let commandWithCRLF = "PASS \(C_FTP_NWConnection_Client_Module.FTP_USER_PW)" + "\r\n"
C_FTP_NWConnection_Client_Module.connection?.send(content: commandWithCRLF.data(using: .utf8), completion: .contentProcessed { error in
if let error = error {
C_FTP_NWConnection_Client_Module.LOGIN_PW_ERROR_LOG = "[Error] : FTP User Pw Error"
S_Log._E_(description: "FTP 로그인 사용자 PW 인증 에러", data: [
"M_LOG :: \(C_FTP_NWConnection_Client_Module.LOGIN_PW_ERROR_LOG)",
"Description :: \(error)"
])
// [콜백 반환]
completion(false)
return
} else {
S_Log._W_(description: "FTP 로그인 사용자 PW 인증 성공", data: [
"commandWithPwCRLF :: \(commandWithCRLF)"
])
// [콜백 반환]
completion(true)
return
}
})
}
else {
C_FTP_NWConnection_Client_Module.LOGIN_PW_ERROR_LOG = "[Error] : Input Data Is Null"
S_Log._E_(description: "FTP 로그인 사용자 PW 인증 수행 에러", data: [
"M_LOG :: \(C_FTP_NWConnection_Client_Module.LOGIN_PW_ERROR_LOG)"
])
// [콜백 반환]
completion(false)
return
}
}
}
// -----------------------------------------------------------------------------------------
// MARK: - [SEARCH FAST] : loginCallbackReturn : FTP 로그인 콜백 처리 수행
// -----------------------------------------------------------------------------------------
func loginCallbackReturn(returnValue: Bool) {
/*
// -----------------------------------------
[loginCallbackReturn 메소드 설명]
// -----------------------------------------
1. FTP 로그인 콜백 처리 수행
// -----------------------------------------
2. 호출 방법 :
self.loginCallbackReturn(returnValue: true)
// -----------------------------------------
3. 필요 import :
import Network
// -----------------------------------------
*/
// -----------------------------------------
// MARK: [True , Flase 에 맞게 변수 초기화 및 로직 처리 수행]
// -----------------------------------------
if returnValue == true { // MARK: [성공]
S_Log._D_(description: "loginCallbackReturn :: 로그인 [성공] 콜백 처리 수행", data: nil)
// [변수 값 초기화]
C_FTP_NWConnection_Client_Module.LOGIN_USER_ERROR_LOG = ""
C_FTP_NWConnection_Client_Module.LOGIN_PW_ERROR_LOG = ""
// MARK: [작업 큐 값 변경 >> 로그인 성공 처리 수행]
C_FTP_NWConnection_Client_Module.connectFlag = true
C_FTP_NWConnection_Client_Module.connectOperationQueue.isSuspended = false
}
else { // MARK: [실패]
S_Log._D_(description: "loginCallbackReturn :: 로그인 [실패] 콜백 처리 수행", data: nil)
// [변수 값 추가]
C_FTP_NWConnection_Client_Module.LOGIN_USER_ERROR_LOG = "[Error] : Login Fail"
C_FTP_NWConnection_Client_Module.LOGIN_PW_ERROR_LOG = "[Error] : Login Fail"
// MARK: [로그인 실패 처리 수행]
if C_FTP_NWConnection_Client_Module.connection != nil && C_FTP_NWConnection_Client_Module.connectFlag == false {
C_FTP_NWConnection_Client_Module.FTP_CONNECT_LOG = "[Login Auth] : FTP Login Fail"
S_Log._E_(description: "FTP 연결 실패", data: [
"M_LOG :: \(C_FTP_NWConnection_Client_Module.FTP_CONNECT_LOG)"
])
// [MQTT 연결 취소]
C_FTP_NWConnection_Client_Module.connection?.cancel()
}
}
}
// -----------------------------------------------------------------------------------------
// MARK: - [SEARCH FAST] : observableUploadFile : 실시간 파일 업로드 수행
// -----------------------------------------------------------------------------------------
// 1. STOR 커맨드 사용해 파일 업로드 상태 전환
// -----------------------------------------------------------------------------------------
// 2. 앱 내부 로컬에 저장 된 파일 send 보내기 수행
// -----------------------------------------------------------------------------------------
static var UPLOAD_ERROR_LOG = ""
func observableUploadFile(fileUrl:String, remoteUrl:String, completion: @escaping (Bool)->()) {
/*
// -----------------------------------------
[observableUploadFile 메소드 설명]
// -----------------------------------------
1. FTP 실시간 파일 전송 수행
// -----------------------------------------
2. 호출 방법 :
C_FTP_NWConnection_Client_Module().observableUploadFile(fileUrl:"file://..", remoteUrl:"/html/crash.txt"){(sendResult) in
S_Log._F_(description: "FTP 실시간 파일 전송 확인", data: ["\(sendResult)"])
if sendResult == true {
}
else {
S_Log._F_(description: "FTP 실시간 파일 전송 에러 메시지", data: ["\(C_FTP_NWConnection_Client_Module.UPLOAD_ERROR_LOG)"])
}
}
// -----------------------------------------
3. 필요 import :
import Network
// -----------------------------------------
*/
// [변수 선언]
C_FTP_NWConnection_Client_Module.UPLOAD_ERROR_LOG = ""
// [로직 처리 수행]
DispatchQueue.global().sync {
S_Log._D_(description: "FTP 파일 업로드 요청 수행", data: nil)
// MARK: [인풋 데이터 널 체크 수행]
if C_FTP_NWConnection_Client_Module.connection != nil
&& C_Util().stringNotNull(str: fileUrl) == true
&& C_Util().stringNotNull(str: remoteUrl) == true {
// MARK: [최종 로그인 커맨드까지 확인이 완료 되어야함] : LOGIN_USER_ERROR_LOG , LOGIN_PW_ERROR_LOG
if C_Util().stringNotNull(str: C_FTP_NWConnection_Client_Module.FTP_SERTVER) == true
&& C_FTP_NWConnection_Client_Module.FTP_PORT > 0
&& C_Util().stringNotNull(str: C_FTP_NWConnection_Client_Module.FTP_USER_NAME) == true
&& C_Util().stringNotNull(str: C_FTP_NWConnection_Client_Module.FTP_USER_PW) == true
&& C_Util().stringNotNull(str: C_FTP_NWConnection_Client_Module.LOGIN_USER_ERROR_LOG) == false
&& C_Util().stringNotNull(str: C_FTP_NWConnection_Client_Module.LOGIN_PW_ERROR_LOG) == false {
// MARK: [FTP 접속 URL 형식 선언]
var remoteFileUrl = ""
if remoteUrl.startsWith(_string: "/") == false {
remoteFileUrl = "/" + remoteUrl
}
else {
remoteFileUrl = remoteUrl
}
let loginUrl = "ftp://\(C_FTP_NWConnection_Client_Module.FTP_USER_NAME):\(C_FTP_NWConnection_Client_Module.FTP_USER_PW)@\(C_FTP_NWConnection_Client_Module.FTP_USER_NAME):\(C_FTP_NWConnection_Client_Module.FTP_PORT)\(remoteFileUrl)" // [파일 경로에는 시작이 / 필요]
S_Log._D_(description: "FTP 클라이언트 >> 서버 파일 업로드 수행", data: ["REMOTE_URL :: \(loginUrl)", "remoteFileUrl :: \(remoteFileUrl)", "LOCAL_FILE :: \(fileUrl)"])
// MARK: [연결 상태 업데이트 핸들러 설정]
let commandWithCRLF = "STOR \(remoteFileUrl)" + "\r\n"
C_FTP_NWConnection_Client_Module.connection?.send(content: commandWithCRLF.data(using: .utf8), completion: .contentProcessed { error in
if let error = error {
C_FTP_NWConnection_Client_Module.UPLOAD_ERROR_LOG = "[Error] : File Upload Command Error"
S_Log._E_(description: "FTP 실시간 파일 전송 Command 에러", data: [
"M_LOG :: \(C_FTP_NWConnection_Client_Module.UPLOAD_ERROR_LOG)",
"Description :: \(error)"
])
completion(false) // [콜백 반환]
return
} else {
S_Log._W_(description: "FTP 실시간 파일 전송 Command 성공", data: [
"commandWithCRLF :: \(commandWithCRLF)"
])
// -----------------------------------------
// MARK: [파일 URL 지정 및 파일 업로드 수행]
// -----------------------------------------
//*
guard let fileData = try? Data(contentsOf: URL(string: fileUrl)!) else {
C_FTP_NWConnection_Client_Module.UPLOAD_ERROR_LOG = "[Fail] : File Url Error"
S_Log._E_(description: "FTP 파일 업로드 연결 실패", data: [
"M_LOG :: \(C_FTP_NWConnection_Client_Module.UPLOAD_ERROR_LOG)"
])
// [콜백 반환]
completion(false)
return
}
C_FTP_NWConnection_Client_Module.connection?.send(content: fileData, completion: .contentProcessed { error in
if let error = error {
C_FTP_NWConnection_Client_Module.UPLOAD_ERROR_LOG = "[Error] : File Upload Message Error"
S_Log._E_(description: "FTP 실시간 파일 전송 에러", data: [
"M_LOG :: \(C_FTP_NWConnection_Client_Module.UPLOAD_ERROR_LOG)",
"Description :: \(error)"
])
completion(false) // [콜백 반환]
return
} else {
S_Log._W_(description: "FTP 실시간 파일 전송 성공", data: [
"URL :: \(loginUrl)"
])
completion(true) // [콜백 반환]
return
}
})
// */
}
})
}
else {
C_FTP_NWConnection_Client_Module.UPLOAD_ERROR_LOG = "[Error] : FTP Login Info Error"
S_Log._E_(description: "FTP 파일 업로드 전송 에러", data: [
"M_LOG :: \(C_FTP_NWConnection_Client_Module.UPLOAD_ERROR_LOG)"
])
completion(false) // [콜백 반환]
return
}
}
else {
C_FTP_NWConnection_Client_Module.UPLOAD_ERROR_LOG = "[Error] : Input Data Is Null"
S_Log._E_(description: "FTP 실시간 파일 전송 에러", data: [
"M_LOG :: \(C_FTP_NWConnection_Client_Module.UPLOAD_ERROR_LOG)"
])
completion(false) // [콜백 반환]
return
}
}
}
// -----------------------------------------------------------------------------------------
// MARK: - [SEARCH FAST] : observableDownloadFile : 실시간 파일 다운로드 수행
// -----------------------------------------------------------------------------------------
// 1. TYPE 커맨드 사용해 바이너리 업로드 상태 전환
// -----------------------------------------------------------------------------------------
// 2. PASV 커맨드 사용해 패시브 모드 상태 전환
// -----------------------------------------------------------------------------------------
// 3. 성공적으로 패시브 모드 전환 시 새롭게 내려온 NEW 서버 주소 파싱 수행 : Entering Passive Mode (112,175,185,132,198,97)
// -----------------------------------------------------------------------------------------
// 4. NWConnection 새롭게 생성 후 ready 상태로 진입 수행
// -----------------------------------------------------------------------------------------
// 5. PASV 커맨드 사용해 로그인 한 커넥션 객체로 send 메시지 전송 (파일 내려 주세요. 요청)
// -----------------------------------------------------------------------------------------
// 6. 신규 NWConnection 객체 reciveFile 리시버에서 파일 다운로드가 응답 되면 앱 내부에 파일 저장 수행
// -----------------------------------------------------------------------------------------
static var DOWNLOAD_ERROR_LOG = ""
static var DOWNLOAD_REMOTE_URL = ""
static var DOWNLOAD_LOCAL_URL = ""
static var downloadOperationQueue = OperationQueue()
func observableDownloadFile(remoteUrl:String, localFileName:String, completion: @escaping (Bool)->()) {
/*
// -----------------------------------------
[observableUploadFile 메소드 설명]
// -----------------------------------------
1. FTP 실시간 파일 전송 수행
// -----------------------------------------
2. 호출 방법 :
C_FTP_NWConnection_Client_Module().observableDownloadFile(remoteUrl: "/html/crash.txt", localFileName:"crash.txt"){(sendResult) in
S_Log._F_(description: "FTP 실시간 파일 다운로드 확인", data: ["\(sendResult)"])
if sendResult == true {
}
else {
S_Log._F_(description: "FTP 실시간 파일 다운로드 에러 메시지", data: ["\(C_FTP_NWConnection_Client_Module.DOWNLOAD_ERROR_LOG)"])
}
}
// -----------------------------------------
3. 필요 import :
import Network
// -----------------------------------------
*/
// [변수 선언]
C_FTP_NWConnection_Client_Module.DOWNLOAD_ERROR_LOG = ""
C_FTP_NWConnection_Client_Module.DOWNLOAD_LOCAL_URL = ""
C_FTP_NWConnection_Client_Module.DOWNLOAD_REMOTE_URL = ""
C_FTP_NWConnection_Client_Module.downloadFlag = false
// MARK: [작업 큐에 추가]
C_FTP_NWConnection_Client_Module.downloadOperationQueue.isSuspended = true
let block = { completion(C_FTP_NWConnection_Client_Module.downloadFlag) }
C_FTP_NWConnection_Client_Module.downloadOperationQueue.addOperation(block)
// [로직 처리 수행]
DispatchQueue.global().sync {
S_Log._D_(description: "FTP 파일 다운로드 요청 수행", data: nil)
// ------------------------------------------------
// MARK: [인풋 데이터 널 체크 수행]
// ------------------------------------------------
if C_FTP_NWConnection_Client_Module.connection != nil
&& C_Util().stringNotNull(str: remoteUrl) == true
&& C_Util().stringNotNull(str: localFileName) == true {
// ------------------------------------------------
// MARK: [최종 로그인 커맨드까지 확인이 완료 되어야함] : LOGIN_USER_ERROR_LOG , LOGIN_PW_ERROR_LOG
// ------------------------------------------------
if C_Util().stringNotNull(str: C_FTP_NWConnection_Client_Module.FTP_SERTVER) == true
&& C_FTP_NWConnection_Client_Module.FTP_PORT > 0
&& C_Util().stringNotNull(str: C_FTP_NWConnection_Client_Module.FTP_USER_NAME) == true
&& C_Util().stringNotNull(str: C_FTP_NWConnection_Client_Module.FTP_USER_PW) == true
&& C_Util().stringNotNull(str: C_FTP_NWConnection_Client_Module.LOGIN_USER_ERROR_LOG) == false
&& C_Util().stringNotNull(str: C_FTP_NWConnection_Client_Module.LOGIN_PW_ERROR_LOG) == false {
// MARK: [FTP 접속 URL 형식 선언]
var remoteFileUrl = ""
if remoteUrl.startsWith(_string: "/") == false {
remoteFileUrl = "/" + remoteUrl
}
else {
remoteFileUrl = remoteUrl
}
// ----------------------------------------------
// MARK: [다운로드 로직 처리를 위한 변수 값 삽입]
// ----------------------------------------------
C_FTP_NWConnection_Client_Module.DOWNLOAD_LOCAL_URL = localFileName
C_FTP_NWConnection_Client_Module.DOWNLOAD_REMOTE_URL = remoteFileUrl
let URL_DATA = "ftp://\(C_FTP_NWConnection_Client_Module.FTP_USER_NAME):\(C_FTP_NWConnection_Client_Module.FTP_USER_PW)@\(C_FTP_NWConnection_Client_Module.FTP_SERTVER):\(C_FTP_NWConnection_Client_Module.FTP_PORT)\(remoteFileUrl)" // [FTP 주소 지정 : 다운로드할 경로를 포함]
S_Log._D_(description: "FTP 클라이언트 >> 서버 파일 다운로드 수행", data: ["REMOTE_URL :: \(URL_DATA)"])
// ----------------------------------------------
// MARK: [바이너리 모드 설정] : [TYPE I]
// ----------------------------------------------
let commandWithCRLF = "TYPE I" + "\r\n"
C_FTP_NWConnection_Client_Module.connection?.send(content: commandWithCRLF.data(using: .utf8), completion: .contentProcessed { error in
if let error = error {
C_FTP_NWConnection_Client_Module.DOWNLOAD_ERROR_LOG = "[Error] : [TYPE] : File Download Command Error"
S_Log._E_(description: "FTP : 실시간 파일 다운로드 [TYPE] Command 에러", data: [
"M_LOG :: \(C_FTP_NWConnection_Client_Module.DOWNLOAD_ERROR_LOG)",
"Description :: \(error)"
])
// [콜백 반환]
C_FTP_NWConnection_Client_Module.downloadOperationQueue.isSuspended = false
return
} else {
S_Log._W_(description: "FTP : 실시간 파일 다운로드 [TYPE] Command 성공", data: [
"commandWithCRLF :: \(commandWithCRLF)"
])
// ----------------------------------------------
// MARK: [receiveData 에서 바이너리 모드 설정 상태 확인]
// ----------------------------------------------
}
})
}
else {
C_FTP_NWConnection_Client_Module.DOWNLOAD_ERROR_LOG = "[Error] : [TYPE] : FTP Login Info Error"
S_Log._E_(description: "FTP 파일 다운로드 에러", data: [
"M_LOG :: \(C_FTP_NWConnection_Client_Module.DOWNLOAD_ERROR_LOG)"
])
// [콜백 반환]
C_FTP_NWConnection_Client_Module.downloadOperationQueue.isSuspended = false
return
}
}
else {
C_FTP_NWConnection_Client_Module.DOWNLOAD_ERROR_LOG = "[Error] : [TYPE] : Input Data Is Null"
S_Log._E_(description: "FTP 파일 다운로드 에러", data: [
"M_LOG :: \(C_FTP_NWConnection_Client_Module.DOWNLOAD_ERROR_LOG)"
])
// [콜백 반환]
C_FTP_NWConnection_Client_Module.downloadOperationQueue.isSuspended = false
return
}
}
}
// -----------------------------------------------------------------------------------------
// MARK: - [SEARCH FAST] : observablePassiveMode : 파일 다운로드 패시브 모드 수행
// -----------------------------------------------------------------------------------------
func observablePassiveMode(completion: @escaping (Bool)->()) {
/*
// -----------------------------------------
[observablePassiveMode 메소드 설명]
// -----------------------------------------
1. 파일 다운로드 패시브 모드 수행
// -----------------------------------------
2. 호출 방법 :
C_FTP_NWConnection_Client_Module().observablePassiveMode(){(sendResult) in
S_Log._F_(description: "FTP 파일 다운로드 패시브 모드 확인", data: ["\(sendResult)"])
if sendResult == true {
}
else {
S_Log._F_(description: "FTP 파일 다운로드 패시브 모드 에러 메시지", data: ["\(C_FTP_NWConnection_Client_Module.DOWNLOAD_ERROR_LOG)"])
}
}
// -----------------------------------------
3. 필요 import :
import Network
// -----------------------------------------
*/
// [로직 처리 수행]
DispatchQueue.global().sync {
S_Log._D_(description: "FTP 파일 다운로드 패시브 모드 요청 수행", data: nil)
// ------------------------------------------------
// MARK: [인풋 데이터 널 체크 수행]
// ------------------------------------------------
// MARK: [최종 로그인 커맨드까지 확인이 완료 되어야함] : LOGIN_USER_ERROR_LOG , LOGIN_PW_ERROR_LOG
// ------------------------------------------------
// MARK: [파일 다운로드 바이너리 모드 요청이 완료 되어야함] : DOWNLOAD_REMOTE_URL , DOWNLOAD_LOCAL_URL
// ------------------------------------------------
if C_FTP_NWConnection_Client_Module.connection != nil
&& C_Util().stringNotNull(str: C_FTP_NWConnection_Client_Module.FTP_SERTVER) == true
&& C_FTP_NWConnection_Client_Module.FTP_PORT > 0
&& C_Util().stringNotNull(str: C_FTP_NWConnection_Client_Module.FTP_USER_NAME) == true
&& C_Util().stringNotNull(str: C_FTP_NWConnection_Client_Module.FTP_USER_PW) == true
&& C_Util().stringNotNull(str: C_FTP_NWConnection_Client_Module.LOGIN_USER_ERROR_LOG) == false
&& C_Util().stringNotNull(str: C_FTP_NWConnection_Client_Module.LOGIN_PW_ERROR_LOG) == false
&& C_Util().stringNotNull(str: C_FTP_NWConnection_Client_Module.DOWNLOAD_REMOTE_URL) == true
&& C_Util().stringNotNull(str: C_FTP_NWConnection_Client_Module.DOWNLOAD_LOCAL_URL) == true {
// ----------------------------------------------
// MARK: [패시브 모드 설정] : [PASV]
// ----------------------------------------------
let commandWithCRLF = "PASV" + "\r\n"
C_FTP_NWConnection_Client_Module.connection?.send(content: commandWithCRLF.data(using: .utf8), completion: .contentProcessed { error in
if let error = error {
C_FTP_NWConnection_Client_Module.DOWNLOAD_ERROR_LOG = "[Error] : [PASV] : File Download Command Error"
S_Log._E_(description: "FTP : 실시간 파일 다운로드 [PASV] Command 에러", data: [
"M_LOG :: \(C_FTP_NWConnection_Client_Module.DOWNLOAD_ERROR_LOG)",
"Description :: \(error)"
])
// [콜백 반환]
completion(false)
return
} else {
S_Log._W_(description: "FTP : 실시간 파일 다운로드 [PASV] Command 성공", data: [
"commandWithCRLF :: \(commandWithCRLF)"
])
// ----------------------------------------------
// MARK: [receiveData 에서 패시브 모드 설정 상태 확인]
// ----------------------------------------------
}
})
}
else {
C_FTP_NWConnection_Client_Module.DOWNLOAD_ERROR_LOG = "[Error] : [PASV] : Input Data Is Null"
S_Log._E_(description: "FTP 파일 다운로드 에러", data: [
"M_LOG :: \(C_FTP_NWConnection_Client_Module.DOWNLOAD_ERROR_LOG)"
])
// [콜백 반환]
completion(false)
return
}
}
}
// -----------------------------------------------------------------------------------------
// MARK: - [SEARCH FAST] : observableNewDownloadConnection : 파일 다운로드 NEW 새로운 접속 수행
// -----------------------------------------------------------------------------------------
static var NEW_CONNECT_LOG = ""
func observableNewDownloadConnection(server: String, port: UInt16, completion: @escaping (Bool)->()) {
/*
// -----------------------------------------
[observableNewDownloadConnection 메소드 설명]
// -----------------------------------------
1. 파일 다운로드 NEW 새로운 접속 IP , PORT 사용해 FTP 연결 수행
// -----------------------------------------
2. 호출 방법 :
C_FTP_NWConnection_Client_Module().observableNewDownloadConnection(server: "128.165.0.4", port: 56123){(connectResult) in
S_Log._F_(description: "NEW 파일 서버 연결 확인 수행", data: ["\(connectResult)"])
if connectResult == true {
// [FTP 연결 완료 로직 처리]
}
else {
S_Log._F_(description: "NEW 파일 서버 연결 에러 메시지", data: ["\(C_FTP_NWConnection_Client_Module.NEW_CONNECT_LOG)"])
}
}
// -----------------------------------------
3. 필요 import :
import Network
// -----------------------------------------
*/
// [변수 선언 및 초기화]
C_FTP_NWConnection_Client_Module.fileNwconnection = nil
C_FTP_NWConnection_Client_Module.NEW_CONNECT_LOG = ""
C_FTP_NWConnection_Client_Module.downloadFlag = false
self.workItem = nil
// [로직 처리 수행]
DispatchQueue.main.async {
S_Log._D_(description: "NEW FTP 파일 서버 연결 수행", data: [ "SERVER :: \(server)", "PORT :: \(port)" ])
// ------------------------------------------------
// MARK: [인풋 데이터 널 체크 수행]
// ------------------------------------------------
// MARK: [파일 다운로드 바이너리 모드 요청이 완료 되어야함] : DOWNLOAD_REMOTE_URL , DOWNLOAD_LOCAL_URL
// ------------------------------------------------
if C_Util().stringNotNull(str: server) == true && port >= 0
&& C_Util().stringNotNull(str: C_FTP_NWConnection_Client_Module.DOWNLOAD_LOCAL_URL) == true
&& C_Util().stringNotNull(str: C_FTP_NWConnection_Client_Module.DOWNLOAD_REMOTE_URL) == true {
// [FTP 연결 옵션 지정]
C_FTP_NWConnection_Client_Module.fileNwconnection = NWConnection(host: NWEndpoint.Host(server), port: NWEndpoint.Port("\(port)")!, using: self.parames)
// [연결 상태 업데이트 핸들러 설정]
C_FTP_NWConnection_Client_Module.fileNwconnection?.stateUpdateHandler = { state in
switch state {
case .ready:
C_FTP_NWConnection_Client_Module.NEW_CONNECT_LOG = "[Success] : New Connection Ready State"
S_Log._W_(description: "NEW FTP 파일 서버 연결 성공", data: [
"M_LOG :: \(C_FTP_NWConnection_Client_Module.NEW_CONNECT_LOG)"
])
// ----------------------------------------------
// MARK: [실시간 파일 다운로드 수신 상태 확인]
// ----------------------------------------------
self.receiveFile()
// ---------------------------------------------
// MARK: [파일 다운로드 요청] : [RETR]
// ---------------------------------------------
// MARK: [SEND] : 요청 보내는 것은 로그인이 된 C_FTP_NWConnection_Client_Module.connection 로 요청 필요
// ---------------------------------------------
S_Log._D_(description: "FTP : 실시간 파일 다운로드 [RETR] Command 요청 수행", data: nil)
let commandWithCRLF = "RETR \(C_FTP_NWConnection_Client_Module.DOWNLOAD_REMOTE_URL)" + "\r\n"
C_FTP_NWConnection_Client_Module.connection?.send(content: commandWithCRLF.data(using: .utf8), completion: .contentProcessed { error in
if let error = error {
C_FTP_NWConnection_Client_Module.DOWNLOAD_ERROR_LOG = "[Error] : [RETR] : File Download Command Error"
S_Log._E_(description: "FTP : 실시간 파일 다운로드 [RETR] Command 에러", data: [
"M_LOG :: \(C_FTP_NWConnection_Client_Module.DOWNLOAD_ERROR_LOG)",
"Description :: \(error)"
])
// [콜백 반환]
if C_FTP_NWConnection_Client_Module.downloadFlag == false {
completion(false)
}
// [객체 초기화]
if C_FTP_NWConnection_Client_Module.fileNwconnection != nil {
C_FTP_NWConnection_Client_Module.fileNwconnection = nil
C_FTP_NWConnection_Client_Module.downloadFlag = false
}
return
} else {
S_Log._W_(description: "FTP : 실시간 파일 다운로드 [RETR] Command 성공", data: [
"commandWithCRLF :: \(commandWithCRLF)"
])
// ----------------------------------------------
// MARK: [receiveData 에서 파일 다운로드 요청 상태 확인] : [150 BINARY 모드로 데이터 연결 열기]
// ----------------------------------------------
C_FTP_NWConnection_Client_Module.downloadFlag = true
}
})
case .failed(let error):
C_FTP_NWConnection_Client_Module.NEW_CONNECT_LOG = "[Fail] : New Connection Fail State"
S_Log._E_(description: "NEW FTP 파일 서버 연결 실패", data: [
"M_LOG :: \(C_FTP_NWConnection_Client_Module.NEW_CONNECT_LOG)",
"Description :: \(error)"
])
// [콜백 반환]
if C_FTP_NWConnection_Client_Module.downloadFlag == false {
completion(false)
}
// [객체 초기화]
if C_FTP_NWConnection_Client_Module.fileNwconnection != nil {
C_FTP_NWConnection_Client_Module.fileNwconnection = nil
C_FTP_NWConnection_Client_Module.downloadFlag = false
}
return
case .cancelled:
C_FTP_NWConnection_Client_Module.NEW_CONNECT_LOG = "[Cancel] : Connection Cancel State"
S_Log._E_(description: "NEW FTP 파일 서버 연결 실패", data: [
"M_LOG :: \(C_FTP_NWConnection_Client_Module.NEW_CONNECT_LOG)"
])
// [콜백 반환]
if C_FTP_NWConnection_Client_Module.downloadFlag == false {
completion(false)
}
// [객체 초기화]
if C_FTP_NWConnection_Client_Module.fileNwconnection != nil {
C_FTP_NWConnection_Client_Module.fileNwconnection = nil
C_FTP_NWConnection_Client_Module.downloadFlag = false
}
return
default:
break
}
}
// [연결 시작]
C_FTP_NWConnection_Client_Module.fileNwconnection?.start(queue: .global())
// ---------------------------------------------
// MARK: [FTP 연결 타임 아웃 처리]
// ---------------------------------------------
self.workItem = DispatchWorkItem {
if C_FTP_NWConnection_Client_Module.fileNwconnection != nil && C_FTP_NWConnection_Client_Module.downloadFlag == false {
C_FTP_NWConnection_Client_Module.NEW_CONNECT_LOG = "[Time Out] : New FTP Connection TimeOut"
S_Log._E_(description: "NEW FTP 파일 서버 연결 실패", data: [
"M_LOG :: \(C_FTP_NWConnection_Client_Module.NEW_CONNECT_LOG)"
])
// [FTP 연결 취소]
C_FTP_NWConnection_Client_Module.fileNwconnection?.cancel()
}
}
let delay = DispatchTime.now() + self.CONNECT_TIME_OUT // [특정 시간 후에 실행]
DispatchQueue.main.asyncAfter(deadline: delay, execute: self.workItem!)
}
else {
C_FTP_NWConnection_Client_Module.NEW_CONNECT_LOG = "[Error] : New Input Data Is Null"
S_Log._E_(description: "NEW FTP 파일 서버 연결 에러", data: [
"M_LOG :: \(C_FTP_NWConnection_Client_Module.NEW_CONNECT_LOG)"
])
// [콜백 반환]
completion(false)
return
}
}
}
// -----------------------------------------------------------------------------------------
// MARK: - [SEARCH FAST] : receiveFile : 실시간 파일 다운로드 수신 상태 확인
// -----------------------------------------------------------------------------------------
private func receiveFile() {
if C_FTP_NWConnection_Client_Module.fileNwconnection != nil {
S_Log._D_(description: "RECEIVE 실시간 파일 다운로드 수신 감지 수행", data: nil)
C_FTP_NWConnection_Client_Module.fileNwconnection?.receive(minimumIncompleteLength: 1, maximumLength: 4096, completion: { data, _, isComplete, error in
// -----------------------------------------------------------------------
// MARK: [FTP 연결 종료 및 객체 초기화]
// -----------------------------------------------------------------------
C_FTP_NWConnection_Client_Module.fileNwconnection?.cancel()
//C_FTP_NWConnection_Client_Module.fileNwconnection = nil
//C_FTP_NWConnection_Client_Module.downloadFlag = false
// -----------------------------------------------------------------------
// MARK: [앱 로컬 저장소에 파일 저장 수행]
// -----------------------------------------------------------------------
if let data = data, !data.isEmpty {
if C_Util().stringNotNull(str: C_FTP_NWConnection_Client_Module.DOWNLOAD_LOCAL_URL) == true {
S_Log._W_(description: "[Ing] ---- [RECEIVE 실시간 파일 다운로드 수신 감지] ---- [Ing]", data: nil)
// -----------------------------------------
// MARK: [로컬 앱 파일 저장 경로 지정 수행]
// -----------------------------------------
// MARK:
// -----------------------------------------
let fileManager = FileManager.default // 파일 매니저 선언
let documentsUrl = fileManager.urls(for: .documentDirectory, in: .userDomainMask).first // 기본 경로 확인
let fileName = C_FTP_NWConnection_Client_Module.DOWNLOAD_LOCAL_URL
var filePath = documentsUrl?.path ?? ""
if (filePath.hasSuffix("/") == true){
filePath = filePath + fileName
}
else {
filePath = filePath + "/" + fileName
}
// -----------------------------------------
// MARK: [로컬 앱 파일 저장 수행]
// -----------------------------------------
if FileManager.default.fileExists(atPath: filePath) == true { // [파일 존재]
let contentData = data
if let handle = try? FileHandle(forWritingTo: NSURL.fileURL(withPath: filePath)) {
handle.seekToEndOfFile() // moving pointer to the end
handle.write(contentData) // adding content
handle.closeFile() // closing the file
C_FTP_NWConnection_Client_Module.NEW_CONNECT_LOG = "[Success] :: [Append] :: File"
}
else {
C_FTP_NWConnection_Client_Module.NEW_CONNECT_LOG = "[Fail] :: [Append] :: File"
}
}
else { // [파일 없음]
do {
let contentData = data
try contentData.write(to: NSURL.fileURL(withPath: filePath), options: Data.WritingOptions.atomic)
C_FTP_NWConnection_Client_Module.NEW_CONNECT_LOG = "[Success] :: [Write] :: File"
} catch {
C_FTP_NWConnection_Client_Module.NEW_CONNECT_LOG = "[Exception] :: [Write] :: \(error.localizedDescription)"
}
}
S_Log._W_(description: "FTP 파일 앱 저장 수행 성공", data: [
"M_LOG :: \(C_FTP_NWConnection_Client_Module.NEW_CONNECT_LOG)"
])
// ---------------------------------------------
// MARK: [FTP 파일 다운로드 성공 콜백 반환]
// ---------------------------------------------
self.downloadCallbackReturn(returnValue: true)
}
else {
C_FTP_NWConnection_Client_Module.NEW_CONNECT_LOG = "[Error] : DOWNLOAD_LOCAL_URL Is Null"
S_Log._E_(description: "FTP 파일 앱 저장 수행 실패", data: [
"M_LOG :: \(C_FTP_NWConnection_Client_Module.NEW_CONNECT_LOG)"
])
// ---------------------------------------------
// MARK: [FTP 파일 다운로드 실패 콜백 반환]
// ---------------------------------------------
self.downloadCallbackReturn(returnValue: false)
}
}
else {
S_Log._E_(description: "[Empty] ---- [RECEIVE 실시간 파일 다운로드 수신 감지] ---- [Empty]", data: nil)
C_FTP_NWConnection_Client_Module.NEW_CONNECT_LOG = "[Error] : File Size Is Null"
S_Log._E_(description: "FTP 파일 앱 저장 수행 실패", data: [
"M_LOG :: \(C_FTP_NWConnection_Client_Module.NEW_CONNECT_LOG)"
])
// ---------------------------------------------
// MARK: [FTP 파일 다운로드 실패 콜백 반환]
// ---------------------------------------------
self.downloadCallbackReturn(returnValue: false)
}
})
}
else {
S_Log._E_(description: "소켓 실시간 메시지 수신 감지 에러 :: connection is null", data: nil)
}
}
// -----------------------------------------------------------------------------------------
// MARK: - [SEARCH FAST] : downloadCallbackReturn : FTP 파일 다운로드 콜백 처리 수행
// -----------------------------------------------------------------------------------------
func downloadCallbackReturn(returnValue: Bool) {
/*
// -----------------------------------------
[downloadCallbackReturn 메소드 설명]
// -----------------------------------------
1. FTP 파일 다운로드 콜백 처리 수행
// -----------------------------------------
2. 호출 방법 :
self.downloadCallbackReturn(returnValue: true)
// -----------------------------------------
3. 필요 import :
import Network
// -----------------------------------------
*/
// -----------------------------------------
// MARK: [True , Flase 에 맞게 변수 초기화 및 로직 처리 수행]
// -----------------------------------------
if returnValue == true { // MARK: [성공]
S_Log._D_(description: "downloadCallbackReturn :: 파일 다운로드 [성공] 콜백 처리 수행", data: nil)
// [변수 값 초기화]
C_FTP_NWConnection_Client_Module.DOWNLOAD_LOCAL_URL = ""
C_FTP_NWConnection_Client_Module.DOWNLOAD_REMOTE_URL = ""
// MARK: [작업 큐 값 변경 >> 로그인 성공 처리 수행]
C_FTP_NWConnection_Client_Module.downloadFlag = true
C_FTP_NWConnection_Client_Module.downloadOperationQueue.isSuspended = false
}
else { // MARK: [실패]
S_Log._D_(description: "downloadCallbackReturn :: 파일 다운로드 [실패] 콜백 처리 수행", data: nil)
// [변수 값 추가]
C_FTP_NWConnection_Client_Module.DOWNLOAD_LOCAL_URL = ""
C_FTP_NWConnection_Client_Module.DOWNLOAD_REMOTE_URL = ""
// MARK: [작업 큐 값 변경 >> 파일 다운로드 실패 처리 수행]
C_FTP_NWConnection_Client_Module.downloadFlag = false
C_FTP_NWConnection_Client_Module.downloadOperationQueue.isSuspended = false
}
}
} // [클래스 종료]
반응형
'투케이2K 유틸파일' 카테고리의 다른 글
Comments