안녕하세요. 후르륵짭짭입니다.
그냥 호기심으로 어떻게 하면 API로 다운로드 상태를 확인 할 수 있지???
로 시작해서 글을 정리 하려고 합니다.
참고로 이미 만들어져 있는 raywenderlich.com을 이용해서 Playground에 연습한거라서
크게 정리할 생각은 없습니다. 왜냐하면 저기가 더 자세하게 작성 되어 있기 때문입니다.
다음에는 URLSession이 아니라 Alamofire로 하는 방법을 자세하게 작성 하도록 하겠습니다.
** NetworkRepository **
class NetworkRepository: NSObject, URLSessionDelegate {
var downloadSession : URLSession?
override init(){
super.init()
self.downloadSession = setURLSession()
}
private func setURLSession() -> URLSession {
let configuration = URLSessionConfiguration.default
return URLSession(configuration: configuration, delegate: self, delegateQueue: nil)
}
func downloadTask(url : URL){
let task = downloadSession?.downloadTask(with: url)
task?.resume()
}
}
1. 기본적인 URLSession을 생성해줍니다.
2.그리고 downloadTask 함수를 통해서 다운로드 함수를 정의해줍니다.
-- URLSessionDelegate을 해주셔야합니다. --
** URLSessionDownloadDelegate **
extension NetworkRepository : URLSessionDownloadDelegate {
func urlSession(_ session: URLSession, downloadTask: URLSessionDownloadTask, didFinishDownloadingTo location: URL) {
print("Finished Downloading to \(location)")
//location은 임시적인 위치입니다. 다운 받고 함수가 끝나면 해당 파일은 사라집니다.
guard let sourcURL = downloadTask.originalRequest?.url else {return}
print("Source URL : \(sourcURL)")
let fileManager = FileManager.default
let documentURL = fileManager.urls(for: .documentDirectory, in: .userDomainMask)[0]
let destinationURL = documentURL.appendingPathComponent(sourcURL.lastPathComponent)
print("Destination URL : " ,destinationURL)
try? fileManager.removeItem(at: destinationURL)
do{
try fileManager.copyItem(at: location, to: destinationURL)
}
catch let error {
print("Could not copy file to disk: \(error.localizedDescription)")
}
}
....
}
1. NetworkRepository에 URLSessionDownloadDelegate를 해주시고
urlSession - session: downloadTask: didFinishDownloadingTo:를 해줍니다.
이 함수는 다운로드가 완료하면 수행되는 함수 입니다.
그래서 이 함수 부분에 (1)파일을 저장할 위치 를 정의 해줬습니다.
-- location은 임시적인 위치입니다. 다운 받고 함수가 끝나면 해당 파일은 사라집니다. --
** 현재 파일 다운로드 상태 추적하기 **
func urlSession(_ session: URLSession, downloadTask: URLSessionDownloadTask, didWriteData bytesWritten: Int64, totalBytesWritten: Int64, totalBytesExpectedToWrite: Int64) {
let currentProgress = Float(totalBytesWritten) / Float(totalBytesExpectedToWrite)
let totalSize = ByteCountFormatter.string(fromByteCount: totalBytesExpectedToWrite, countStyle: .file)
print("current Progress : \(currentProgress) / totalSize : \(totalSize)")
}
해당 함수는 URLSessionDownloadDelegate 에 있는 함수 입니다.
(1) totalBytesWritten은 현재 다운 받은 정도
(2) totalBytesExpectedToWrite은 다운 받아야하는 양
을 의미합니다.
ByteCountFormatter.string(fromByteCount: totalBytesExpectedToWrite, countStyle: .file)
해당 코드는 Int의 값을 Byte로 되어있는 원하는 타입의 형태로 사용자가 쉽게 볼 수 있도록 변형 해줍니다.
** 호출 **
class TestView {
let repository = NetworkRepository()
init(){
if let url = URL(string: "https://file-examples-com.github.io/uploads/2017/10/file-example_PDF_1MB.pdf") {
repository.downloadTask(url: url)
}
}
}
let test = TestView()
저는 그냥 간단하게 다음과 같이 호출 했습니다.
** 결과 **
current Progress : 0.0022347881 / totalSize : 1 MB
current Progress : 0.040562987 / totalSize : 1 MB
current Progress : 0.04452976 / totalSize : 1 MB
current Progress : 0.04716564 / totalSize : 1 MB
current Progress : 0.049810153 / totalSize : 1 MB
current Progress : 0.05245467 / totalSize : 1 MB
current Progress : 0.055099186 / totalSize : 1 MB
current Progress : 0.0577437 / totalSize : 1 MB
current Progress : 0.060388215 / totalSize : 1 MB
current Progress : 0.20382822 / totalSize : 1 MB
current Progress : 0.4237356 / totalSize : 1 MB
current Progress : 0.64445853 / totalSize : 1 MB
current Progress : 0.8957911 / totalSize : 1 MB
current Progress : 1.0 / totalSize : 1 MB
Finished Downloading to file:///Users/taesooyoon/Library/Developer/XCPGDevices/AD3ACB57-447C-4B32-A551-8CAA21B75ABD/data/Containers/Data/Application/67BDE4C2-1CE4-4049-82DE-DE7ED56D7386/tmp/CFNetworkDownload_uCzv0c.tmp
Source URL : https://file-examples-com.github.io/uploads/2017/10/file-example_PDF_1MB.pdf
Destination URL : file:///Users/taesooyoon/Library/Developer/XCPGDevices/AD3ACB57-447C-4B32-A551-8CAA21B75ABD/data/Containers/Data/Application/67BDE4C2-1CE4-4049-82DE-DE7ED56D7386/Documents/file-example_PDF_1MB.pdf
** 코드 **
import UIKit
class NetworkRepository: NSObject, URLSessionDelegate {
var downloadSession : URLSession?
override init(){
super.init()
self.downloadSession = setURLSession()
}
private func setURLSession() -> URLSession {
let configuration = URLSessionConfiguration.default
return URLSession(configuration: configuration, delegate: self, delegateQueue: nil)
}
func downloadTask(url : URL){
let task = downloadSession?.downloadTask(with: url)
task?.resume()
}
}
extension NetworkRepository : URLSessionDownloadDelegate {
func urlSession(_ session: URLSession, downloadTask: URLSessionDownloadTask, didFinishDownloadingTo location: URL) {
print("Finished Downloading to \(location)")
guard let sourcURL = downloadTask.originalRequest?.url else {return}
print("Source URL : \(sourcURL)")
let fileManager = FileManager.default
let documentURL = fileManager.urls(for: .documentDirectory, in: .userDomainMask)[0]
let destinationURL = documentURL.appendingPathComponent(sourcURL.lastPathComponent)
print("Destination URL : " ,destinationURL)
try? fileManager.removeItem(at: destinationURL)
do{
try fileManager.copyItem(at: location, to: destinationURL)
}
catch let error {
print("Could not copy file to disk: \(error.localizedDescription)")
}
}
func urlSession(_ session: URLSession, downloadTask: URLSessionDownloadTask, didWriteData bytesWritten: Int64, totalBytesWritten: Int64, totalBytesExpectedToWrite: Int64) {
let currentProgress = Float(totalBytesWritten) / Float(totalBytesExpectedToWrite)
let totalSize = ByteCountFormatter.string(fromByteCount: totalBytesExpectedToWrite, countStyle: .file)
print("current Progress : \(currentProgress) / totalSize : \(totalSize)")
}
}
class TestView {
let repository = NetworkRepository()
init(){
if let url = URL(string: "https://file-examples-com.github.io/uploads/2017/10/file-example_PDF_1MB.pdf") {
repository.downloadTask(url: url)
}
}
}
let test = TestView()
참고 사이트 :
- 강의 사이트
https://www.raywenderlich.com/3244963-urlsession-tutorial-getting-started
- 한글 번역 사이트
- 파일URL로 파일 사이즈 구하기
https://www.codegrepper.com/code-examples/swift/swift+file+size+from+url
- 파일URL로 파일 사이즈 구하기2
https://nemecek.be/blog/22/how-to-get-file-size-using-filemanager-formatting
- HTTP Get의 파일 사이즈 구하기
https://gist.github.com/fethica/3ad09bcbc56ace668d9bb96ad15224a7
'Xcode > Swift - PlayGround' 카테고리의 다른 글
PlayGround) Operation Queue - 2 (0) | 2022.01.17 |
---|---|
PlayGround) Opeation Queue - 1 (0) | 2022.01.17 |
PlayGround)Enum의 활용 (0) | 2021.09.22 |
PlayGround) Notification Center의 사용법 (0) | 2021.09.03 |
PlayGround) RxMvvm에서 Input과 Output에서 의문점 (0) | 2021.09.03 |
댓글