일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | ||
6 | 7 | 8 | 9 | 10 | 11 | 12 |
13 | 14 | 15 | 16 | 17 | 18 | 19 |
20 | 21 | 22 | 23 | 24 | 25 | 26 |
27 | 28 | 29 | 30 |
- rethinkdb
- Materials
- centos
- appium
- Jupyter
- nohup
- insert
- openpyxl
- ssh
- 28015
- sshpass
- ftp
- appium server
- postgresql
- 실행권한
- GoCD
- create table
- mysql
- SWIFT
- kitura
- port forwarding
- STF
- ubuntu
- postgres
- Jupyter Notebook
- PYTHON
- nmap
- STF_PortForwarding
- perfect
- nGrinder
- Today
- Total
don't stop believing
이미지 업로드와 static file (이미지, html) 보기 본문
Perfect로 이미지를 업로드하고 이미지를 확인해 보겠습니다.
언제나 그렇듯이 swift 버전을 확인하고 가겠습니다.
123$ swift -versionApple Swift version 4.0.3 (swiftlang-900.0.74.1 clang-900.0.39.2)Target: x86_64-apple-macosx10.9
프로젝트 폴더를 만들고 이동합니다. 그리고 swift package init으로 초기화 합니다.
12345678910$ mkdir nGleServer014$ cd nGleServer014TongChunui-MacBook-Pro:nGleServer014 tongchunkim$ swift package init --type executableCreating executable package: nGleServer014Creating Package.swiftCreating README.mdCreating .gitignoreCreating Sources/Creating Sources/nGleServer014/main.swiftCreating Tests/
xcodeproj 파일을 생성하고 열어줍니다.
12$ swift package generate-xcodeproj$ open nGleServer014.xcodeproj/
xcode가 실행되면 Package.swift 파일에 PerfectHTTPServer를 추가합니다.
1234567891011121314// swift-tools-version:4.0import PackageDescriptionlet package = Package(name: "nGleServer014",dependencies: [.package(url: "https://github.com/PerfectlySoft/Perfect-HTTPServer.git", from: "3.0.0"),],targets: [.target(name: "nGleServer014",dependencies: ["PerfectHTTPServer",]),])
xcode를 닫고 swift package update와 swift build를 해줍니다.
12$ swift package update$ swift build
그리고 webroot 폴더를 만들고 그 안에 업로드한 이미지를 받을 images와 html 파일을 담을 docs 폴더를 만들어 줍니다.
그리고 main.swift가 있는 위치에 controller.swift 파일을 만들어 줍니다. 서버 실행과 route를 분산해 줄겁니다.
12345$ mkdir webroot$ cd webroot/$ mkdir images docs$ cd ../Sources/nGleServer014/$ touch controller.swift
전체 폴더의 tree 구조는 아래와 같이 만들어 집니다.
123456789101112131415161718192021222324252627282930313233343536373839$ tree.├── Package.resolved├── Package.swift├── README.md├── Sources│·· └── nGleServer014│·· ├── controller.swift│·· └── main.swift├── Tests├── nGleServer014.xcodeproj│·· ├── COpenSSL_Info.plist│·· ├── PerfectCHTTPParser_Info.plist│·· ├── PerfectCZlib_Info.plist│·· ├── PerfectCrypto_Info.plist│·· ├── PerfectHTTPServer_Info.plist│·· ├── PerfectHTTP_Info.plist│·· ├── PerfectLib_Info.plist│·· ├── PerfectNet_Info.plist│·· ├── PerfectThread_Info.plist│·· ├── project.pbxproj│·· ├── project.xcworkspace│·· │·· ├── contents.xcworkspacedata│·· │·· └── xcuserdata│·· │·· └── tongchunkim.xcuserdatad│·· │·· └── UserInterfaceState.xcuserstate│·· ├── xcshareddata│·· │·· └── xcschemes│·· │·· ├── nGleServer014-Package.xcscheme│·· │·· └── xcschememanagement.plist│·· └── xcuserdata│·· └── tongchunkim.xcuserdatad│·· └── xcschemes│·· ├── nGleServer014.xcscheme│·· └── xcschememanagement.plist└── webroot├── docs└── images└── dejavu_1517991366.jpg
이제 다시 xcodeproj를 만들어 주고 열어 봅니다.
12$ swift package generate-xcodeproj$ open nGleServer014.xcodeproj/
먼저 main.swift로 이동합니다.
Controller 클래스는 아직 안만들었지만 우선 아래와 같이 작성합니다.
123456789101112131415import PerfectLibimport PerfectHTTPimport PerfectHTTPServerlet server = HTTPServer()server.serverPort = 8080let control = Controller()server.addRoutes(Routes(control.routes))do {try server.start()} catch PerfectError.networkError(let err, let msg) {print("Network error thrown: \(err) \(msg)")}
이제 controller.swift로 이동합니다.
import먼저 해줍니다.
1234import Foundationimport PerfectLibimport PerfectHTTPimport PerfectHTTPServer
이제 request로 들어오는 json 데이터 key 정보들을 정의합니다.
json 데이터가 많아지면 계속 추가하면 됩니다.
12345struct JSONKey {static let userName = "user_name"static let image = "image"static let imagePath = "image_path"}
이제 Controller 클레스를 만들고 routes를 정의합니다.
이미지를 업로드할 uri와 이미지를 볼 uri를 추가하고 그에 맞는 handler를 추가합니다. handler 함수는 아래에 설명됩니다.
123456789final class Controller {var routes: [Route] {return [Route(method: .post, uri: "/upload", handler: uploadImage),Route(method: .get, uri: "/image/**", handler: viewImage),]}}
request로 전달되는 데이터 중 필수로 지정된 key가 모두 있는지 확인하는 함수를 만들어 줍니다.
필수로 지정된 key가 모두 있다면 nil을 반환하고 부족하다면 Array로 반환됩니다. 이후 옵셔널 체인(if let)으로 처리합니다.
123456789101112func lakedParams(_ paramsNeeded: [String], _ paramsReceived: [(String, String)]) -> [String]? {var laked: [String] = []for param in paramsNeeded {if paramsReceived.filter({ (key, _) -> Bool inreturn key == param}).isEmpty {laked.append(param)}}return laked.count > 0 ? laked : nil}
이미지 저장 디렉토리를 불러옵니다.
이미지가 저장될 폴더는 ./webroot/images 입니다.
1234567891011121314let imageDir: Dir? = {let imageDir = Dir("./webroot/images")if imageDir.exists == false {do {try imageDir.create()print("Working Directory (\(imageDir.path)) for examples created.")} catch {print("Could not create Working Directory for examples.")return nil}}return imageDir}()
response로 전달할 함수를 만들어 줍니다.
12345678910func returnMessage(result: Int, data: [String: Any], response: HTTPResponse) {do {try response.setBody(json: ["result": result, "data": data, "ts": Date().ticks]).setHeader(.contentType, value: "application/json").completed()} catch {response.setBody(string: "Error handling request: \(error)").completed(status: .internalServerError)}}
timestamp를 만들기 위해 extension Date도 해줍니다.
12345extension Date {var ticks: UInt64 {return UInt64((self.timeIntervalSince1970 + 62_135_596_800) * 10_000_000)}}
드디어 upload 함수를 만들 차례입니다.
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455func uploadImage(request: HTTPRequest, response: HTTPResponse) {// 부족한 매개변수가 없는지 확인합니다.let needParams = [JSONKey.userName]if let lakedParams = lakedParams(needParams, request.postParams) {let returnData = ["error": "필수 key가 전달되지 않았습니다. \(lakedParams)"] as [String: Any]returnMessage(result: 1001, data: returnData, response: response)return}// 이미지 파일이 업로드 되었는지 확인guard let imageInformation: MimeReader.BodySpec = request.postFileUploads?.first,let imageFile = imageInformation.file else {let returnData = ["error": "이미지 파일이 전달되지 않았습니다."] as [String: Any]returnMessage(result: 1002, data: returnData, response: response)return}// 사용자 이름 추출guard let userName = request.param(name: JSONKey.userName) else {let returnData = ["error": "사용자 이름 추출에 실패했습니다."] as [String: Any]returnMessage(result: 1003, data: returnData, response: response)return}// 이미지가 저장될 디렉터리guard let imageDirectory = imageDir else {let returnData = ["error": "이미지가 저장될 디렉터리를 확인하지 못했습니다."] as [String: Any]returnMessage(result: 1004, data: returnData, response: response)return}// 고유한 이미지 이름을 위해 타임스템프 값을 활용let timestamp: Int = icuDateToSeconds(getNow())// 사용자이름_타임스템프.jpg 형식으로 파일이름 지정let imageFileName: String = userName + "_" + String(timestamp) + ".jpg"// 이미지가 저장될 경로let imageFilePath: String = imageDirectory.path + imageFileName// 이미지 저장에 실패할 경우 실패 응답 보내기do {try imageFile.copyTo(path: imageFilePath, overWrite: false)} catch {response.completed(status: .internalServerError)return}let imageUrl = "http://" + server.serverAddress + ":\(server.serverPort)" + "/image/" + imageFileNamelet returnData = [JSONKey.userName: userName, JSONKey.imageUrl: imageUrl]returnMessage(result: 0, data: returnData, response: response)}
이제 Postman으로 데이터를 전달해 봅시다.
response 데이터가 잘 옵니다.
xcode에서 webroot/images 폴더에 이미지가 업로드 되는지도 확인해 줍니다.
여러번 테스트했는데 모두 잘 들어오고 있습니다.
이제 이미지를 불러 봅시다.
이미지를 보기위해 위에서 route에 get method를 추가했었습니다.
Route(method: .get, uri: "/image/**", handler: viewImage),
viewImage 함수는 아래와 같이 작성합니다.
12345func viewImage(request: HTTPRequest, response: HTTPResponse) {request.path = request.urlVariables[routeTrailingWildcardKey]!let handler = StaticFileHandler(documentRoot: "webroot/images", allowResponseFilters: true)handler.handleRequest(request: request, response: response)}
이미지를 upload하고 response로 받은 데이터의 image_url 값을 브라우저로 불러 봅니다.
http://0.0.0.0:8080/image/dejavu_1517993432.jpg
viewImage() 함수는 이미지나 html처럼 static한 데이터를 보는데 사용할 수 있습니다.
여기까지 입니다.
'Swift > Perfect' 카테고리의 다른 글
Web 서버 기본 구성 1 (기본 구성과 mustache 확인) (0) | 2018.06.18 |
---|---|
Perfect에서 여러 방법으로 데이터 전달하기 (HTTPRequest) (0) | 2018.06.09 |
json 파일로 config를 관리해 봅시다. (0) | 2018.01.31 |
Perfect로 redis에 연결해 봅시다. 2 (0) | 2018.01.22 |
Perfect로 redis에 연결해 봅시다. 1 (0) | 2018.01.17 |