原理
CocoaHTTPServer框架能够在iOS上建立起一个本地服务器,只要电脑和移动设备连入同一热点,即可使用电脑访问iOS服务器的页面,利用POST实现文件的上传。
实现
CocoaHTTPServer没有现成的向iOS设备传输的Sample,我通过学习OS X端的Sample实现了iOS端的文件传输,按照下面的步骤配置即可。
1.下载CocoaHTTPServer
2.解压后,将CocoaHTTPServer-master目录下的Core导入工程。
3.打开Samples/SimpleFileUploadServer,将其中的MyHTTPConnection类文件、web文件夹导入工程。
4.打开Vendor,将其中的CocoaAsyncSocket、CocoaLumberjack文件夹导入。
5.打开工程,打开MyHTTPConnection.m,根据标记#pragma mark multipart form data parser delegate跳转或者直接找到139行,- (void) processStartOfPartWithHeader:(MultipartMessageHeader*) header方法,将其中filePath的值修改为iOS的某个目录,这个路径是上传的文件存储的路径,这里以Caches为例:
// NSString* uploadDirPath = [[config documentRoot] stringByAppendingPathComponent:@"upload"];
NSString *uploadDirPath = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) lastObject];
6 例子如下
var localHttpServer:HTTPServer!
func setupLocalHttpServer() {
// setupLocalHttpServer()\
localHttpServer = HTTPServer.init()
localHttpServer.setType("_http.tcp")
let fileM = FileManager.init()
// YalaaUpload
if let webPath = Bundle.main.path(forResource: "web", ofType: nil) {
if fileM.fileExists(atPath: webPath) {
print("web \(webPath)")
localHttpServer.setDocumentRoot(webPath)
localHttpServer.setConnectionClass(MyHTTPConnection.classForCoder())
// [httpServer setConnectionClass:[MyHTTPConnection class]];
self.startServer()
}
}
}
func startServer() {
do {
try localHttpServer.start()
let port = localHttpServer.listeningPort()
print("port \(port)")
if let ip = self.getWifiIP() {
print("address http://\(ip):\(port)")
}
} catch let err {
print("error \(err)")
}
}
//获取本机无线局域网ip
func getWifiIP() -> String? {
var address: String?
var ifaddr: UnsafeMutablePointer<ifaddrs>? = nil
guard getifaddrs(&ifaddr) == 0 else {
return nil
}
guard let firstAddr = ifaddr else {
return nil
}
for ifptr in sequence(first: firstAddr, next: { $0.pointee.ifa_next }) {
let interface = ifptr.pointee
// Check for IPV4 or IPV6 interface
let addrFamily = interface.ifa_addr.pointee.sa_family
if addrFamily == UInt8(AF_INET) || addrFamily == UInt8(AF_INET6) {
// Check interface name
let name = String(cString: interface.ifa_name)
if name == "en0" {
// Convert interface address to a human readable string
var addr = interface.ifa_addr.pointee
var hostName = [CChar](repeating: 0, count: Int(NI_MAXHOST))
getnameinfo(&addr,socklen_t(interface.ifa_addr.pointee.sa_len), &hostName, socklen_t(hostName.count), nil, socklen_t(0), NI_NUMERICHOST)
address = String(cString: hostName)
}
}
}
freeifaddrs(ifaddr)
return address
}
注意事项如果没有网络请求的情况下,您的app 是无法获取到网络权限的,获取不到网络权限,您的app 就无法使用局域网传输文件建议您在设置之前,这样加句代码
import Alamofire
enum ApiUrl:String {
case baidu = "https://www.cnblogs.com/ybw123321/p/5359911.html"
}
extension ApiUrl: URLConvertible {
/// Returns a `URL` if `self` can be used to initialize a `URL` instance, otherwise throws.
///
/// - Returns: The `URL` initialized with `self`.
/// - Throws: An `AFError.invalidURL` instance.
public func asURL() throws -> URL {
guard let url = URL(string: self.rawValue) else { throw AFError.invalidURL(url: self) }
return url
}
}
let re = Alamofire.AF.request(ApiUrl.baidu, method: HTTPMethod.get)
re.response { res in
let mm = res.result
switch mm {
case .success(let data):
print("data \(data)")
case .failure(let error):
print("error \(error)")
}
}