Notice
Recent Posts
Recent Comments
Link
투케이2K
161. (ios/swift) 파일 매니저 (FileManager) , http 통신 사용해 웹뷰에서 파일 다운로드 수행 실시 본문
[개발 환경 설정]
개발 툴 : XCODE
개발 언어 : SWIFT
[사전 설정]
[파일 다운로드 주소 감지 부분 : a 태그 href 감지]
// MARK: - [웹뷰 실시간 url 변경 감지 실시]
func webView(_ webView: WKWebView, decidePolicyFor navigationAction: WKNavigationAction, decisionHandler: @escaping (WKNavigationActionPolicy) -> Void) {
// -----------------------------------------
let _shouldUrl = String(describing: webView.url?.description ?? "")
var action: WKNavigationActionPolicy?
defer {
decisionHandler(action ?? .allow)
}
guard let url = navigationAction.request.url else { return }
print("")
print("===============================")
print("[A_Main >> decidePolicyFor() :: 웹뷰 실시간 url 변경 감지]")
print("_shouldUrl :: \(_shouldUrl)")
print("requestUrl :: \(url)")
print("===============================")
print("")
// -----------------------------------------
// [SEARCH FAST] : [파일 다운로드 수행]
if "\(url)".hasPrefix("f:") {
// [주소에서 파일 확장자 확인]
let fileUrl = "\(url)".subString(_start: 2, _end: "\(url)".count-1) // 주소
let fileExtension = C_Util().urlFileExtensionName(string: fileUrl) // 확장자
print("")
print("===============================")
print("[A_Main >> decidePolicyFor() :: 웹뷰 실시간 url 변경 감지]")
print("로 직 :: 파일 다운로드 로직 처리 실시")
print("fileUrl :: \(fileUrl)")
print("fileExtension :: \(fileExtension)")
print("===============================")
print("")
// [파일 확장자 널 체크 수행]
if C_Util().stringNotNull(str: fileExtension) == true { // [파일 확장자 널 아님]
// [로딩 프로그레스 호출]
self.progressStart(onView: self.view)
// [파일 다운로드 및 저장 실시]
C_Util().appDownloadFile(onView: self.view, fileUrl: fileUrl){(result, msg) in
print("")
print("===============================")
print("[A_Main >> decidePolicyFor() :: 웹뷰 실시간 url 변경 감지]")
print("콜 백 :: 파일 다운로드 결과 확인")
print("result :: ", result)
print("msg :: ", msg)
print("===============================")
print("")
// [로딩 프로그레스 종료]
self.progressStop()
// [에러 메시지 분기 처리]
if result == true { // [정상]
self.showAlert(
type:0,
tittle: S_FinalData.AL_FILE,
content: S_FinalData.AL_DOWN_SUCCESS,
okBtb: S_FinalData.AL_OK,
noBtn: "")
}
else { // [실패]
self.showAlert(
type:0,
tittle: S_FinalData.AL_FILE,
content: S_FinalData.AL_DOWN_FAIL + " " + msg,
okBtb: S_FinalData.AL_OK,
noBtn: "")
}
}
}
else { // [파일 확장자 널 데이터]
print("")
print("===============================")
print("[A_Main >> decidePolicyFor() :: 웹뷰 실시간 url 변경 감지]")
print("로 직 :: 파일 다운로드 로직 처리 에러")
print("error :: FILE EXTENSION IS NULL")
print("===============================")
print("")
// [팝업창 알림]
}
}
// -----------------------------------------
}
[파일 다운로드 수행 부분]
// MARK: - [비동기 http 파일 다운로드 수행 실시]
func appDownloadFile(onView : UIView, fileUrl : String, completion: @escaping (Bool, String)->()) {
/*
// -----------------------------------------
[appDownloadFile 메소드 설명]
// -----------------------------------------
1. 파일 다운로드 수행 실시 메소드 (아이폰 >> 파일 폴더 >> 나의 iPhone >> 애플리케이션 >> 저장)
// -----------------------------------------
2. 호출 방법 :
C_Util().appDownloadFile(onView: self.view, fileUrl: "http://img.championat.com/news/big/l/c/ujejn-runi_1439911080563855663.jpg"){(result, msg) in
print("")
print("====================================")
print("[A_Main >> decidePolicyFor() :: 웹뷰 실시간 url 변경 감지]")
print("콜 백 :: 파일 다운로드 결과 확인")
print("result :: ", result)
print("msg :: ", msg)
print("====================================")
print("")
// [에러 메시지 분기 처리]
if result == true { // [정상]
}
else { // [실패]
}
}
// -----------------------------------------
3. 사전 설정 사항 :
- 필요 info plist 설정
[1] http 허용 : App Transport Security Settings >> Allow Arbitrary Loads >> YES
[2] 아이폰 파일 접근 설정 : Supports opening documents in place : YES
[3] 아이튠즈 공유 설정 : Application supports iTunes file sharing : YES
// -----------------------------------------
4. 로직 :
- 인풋으로 들어온 파일 주소 널 체크 수행 실시
- 현재 날짜 및 시간 확인 실시
- 파일 확장자 확인 실시
- 파일이 저장될 경로 설정 수행 실시
- URLSession 사용해 비동기 http 요청 및 파일 다운로드 수행 및 저장 실시
- 파일 저장 명칭은 현재 날짜 및 시간.확장자
// -----------------------------------------
5. 참고 : html a 태그 소스 코드
<a href='f:http://img.championat.com/news/big/l/c/ujejn-runi_1439911080563855663.jpg' download="file"> 파일다운로드 </a>
// -----------------------------------------
*/
// [인풋 데이터 널 체크 수행 실시]
if fileUrl != nil
&& fileUrl.count>0
&& fileUrl != ""
&& fileUrl != "null"
&& fileUrl.isEmpty == false
&& fileUrl.hasPrefix("http"){
// [URL 타입 선언 확인 실시]
guard let urlCheck = URL(string: fileUrl)
else {
print("")
print("====================================")
print("[C_Util >> appDownloadFile() :: URL 주소 파일 확장자 포함 확인 에러]")
print("-------------------------------")
print("error :: ", "URL 파싱 에러")
print("====================================")
print("")
// [콜백 반환]
completion(false, "[appDownloadFile] : url parsing error")
return
}
// [현재 날짜 및 시간 확인 실시]
let nowDate = Date() // 현재의 Date 날짜 및 시간
let dateFormatter = DateFormatter() // Date 포맷 객체 선언
dateFormatter.locale = Locale(identifier: "ko") // 한국 지정
dateFormatter.dateFormat = "yyyyMMddkkmmss" // Date 포맷 타입 지정
//dateFormatter.dateFormat = "kkmmss" // Date 포맷 타입 지정
let date_string = dateFormatter.string(from: nowDate) // 포맷된 형식 문자열로 반환
// [파일 확장자 및 이름 확인 실시]
var fileExtension = String(describing: urlCheck.pathExtension) // [jpg]
let fileOriginName = String(describing: urlCheck.lastPathComponent) // [file.jpg]
// [파일 확장자명 종료 확인]
if fileExtension != nil && fileExtension.count>0 && fileExtension != "" {
}
else {
guard let lastEIndex = fileUrl.lastIndex(of: "/") else { fatalError() } // 마지막 / 문자 인덱스 위치
let endIndex = fileUrl.index(fileUrl.startIndex, offsetBy: fileUrl.count-1)
var files = String(fileUrl[lastEIndex...endIndex]) // 문자열 분리 실시
files = files.replacingOccurrences(of: "/", with: "") // 불필요 문자 제거
let arrays = files.components(separatedBy: ".")
if arrays != nil && arrays.isEmpty == false && arrays.count>0 && arrays.count == 2 { // [. 기준으로 정상적으로 분리가 된 경우]
// [변수에 삽입 실시]
fileExtension = arrays[1]
}
}
// [최종 파일 명칭 확인 실시]
if fileExtension != nil && fileExtension.count>0 && fileExtension != "" {
// [현재 날짜 및 시간 + 파일 확장자 데이터 결합 실시]
let fileName = date_string + "." + fileExtension
// [파일이 저장될 경로 설정 실시]
let fileManager = FileManager.default // 파일 매니저 선언
let documentsUrl = fileManager.urls(for: .documentDirectory, in: .userDomainMask).first! // 기본 경로 확인
let fileSavePath = documentsUrl.appendingPathComponent(fileName) // 실제 저장되는 경로
// [http 비동기 방식을 사용해서 파일 다운로드 및 저장 수행 실시]
var urlComponents = URLComponents(string: fileUrl)
var requestURL = URLRequest(url: (urlComponents?.url)!)
requestURL.httpMethod = "GET" // GET
requestURL.addValue("application/x-www-form-urlencoded; charset=utf-8;", forHTTPHeaderField: "Content-Type") // GET
print("")
print("====================================")
print("[C_Util >> appDownloadFile() :: http 통신 파일 다운로드 요청 실시]")
print("-------------------------------")
print("주 소 :: ", requestURL)
print("-------------------------------")
print("파일 저장 경로 :: ", fileSavePath)
print("====================================")
print("")
// [http 요쳥을 위한 URLSessionDataTask 생성]
let dataTask = URLSession.shared.dataTask(with: requestURL, completionHandler: { (data, response, error) in
// [error가 존재하면 종료]
guard error == nil else {
print("")
print("====================================")
print("[C_Util >> appDownloadFile() :: http 통신 파일 다운로드 요청 실패]")
print("-------------------------------")
print("주 소 :: ", requestURL)
print("-------------------------------")
print("fail :: ", error?.localizedDescription ?? "")
print("====================================")
print("")
// [콜백 반환]
completion(false, error?.localizedDescription ?? "")
return
}
// [status 코드 체크 실시]
let successsRange = 200..<300
guard let statusCode = (response as? HTTPURLResponse)?.statusCode, successsRange.contains(statusCode)
else {
print("")
print("====================================")
print("[C_Util >> appDownloadFile() :: http 통신 파일 다운로드 요청 에러]")
print("-------------------------------")
print("주 소 :: ", requestURL)
print("-------------------------------")
print("error :: ", (response as? HTTPURLResponse)?.statusCode ?? 0)
print("-------------------------------")
print("msg :: ", (response as? HTTPURLResponse)?.description ?? "")
print("====================================")
print("")
// [콜백 반환]
completion(false, (response as? HTTPURLResponse)?.description ?? "")
return
}
// [response 데이터 획득]
let resultCode = (response as? HTTPURLResponse)?.statusCode ?? 0
let resultLen = data! // 데이터 길이
print("")
print("====================================")
print("[C_Util >> appDownloadFile() :: http 통신 파일 다운로드 성공]")
print("-------------------------------")
print("주 소 :: ", requestURL)
print("-------------------------------")
print("resultCode :: ", resultCode)
print("-------------------------------")
print("resultLen :: ", resultLen)
print("====================================")
print("")
// [파일 저장 수행 실시]
if let data = data {
// [설정한 경로에 파일 저장]
if let _ = try? data.write(to: fileSavePath, options: Data.WritingOptions.atomic) {
print("")
print("====================================")
print("[C_Util >> appDownloadFile() :: http 통신 파일 저장 [성공]]")
print("-------------------------------")
print("파일 저장 경로 :: ", fileSavePath)
print("====================================")
print("")
// [콜백 반환]
completion(true, "[appDownloadFile] : File Download Success")
}
else {
print("")
print("====================================")
print("[C_Util >> appDownloadFile() :: http 통신 파일 저장 [실패] [1]]")
print("-------------------------------")
print("파일 저장 경로 :: ", fileSavePath)
print("-------------------------------")
print("error :: ", "data write error")
print("====================================")
print("")
// [콜백 반환]
completion(false, "[appDownloadFile] : data write error")
}
}
else {
print("")
print("====================================")
print("[C_Util >> appDownloadFile() :: http 통신 파일 저장 [실패] [2]]")
print("-------------------------------")
print("파일 저장 경로 :: ", fileSavePath)
print("-------------------------------")
print("error :: ", "data parsing error")
print("====================================")
print("")
// [콜백 반환]
completion(false, "[appDownloadFile] : data parsing error")
}
})
// [network 통신 실행]
dataTask.resume()
}
else {
print("")
print("====================================")
print("[C_Util >> appDownloadFile() :: http 통신 파일 다운로드 요청 에러]")
print("-------------------------------")
print("error :: ", "file extension is null")
print("====================================")
print("")
// [콜백 반환]
completion(false, "[appDownloadFile] : file extension is null")
return
}
}
else {
// [콜백 반환]
completion(false, "[appDownloadFile] : Input data is null")
}
}
[결과 출력]
반응형
'IOS' 카테고리의 다른 글
Comments