由于iOS系统的封闭性,在数据传输方面十分不方便。不像安卓设备,直接连接电脑就能当U盘使用。所以一般我们如果用iPhone临时存取个东西,要么使用数据线连接iTunes,要么手机电脑都登上QQ,使用QQ来传输。

但这两种方式都略显不便,所以市面上出现了无线U盘这类的APP。原理很简单,就是软件打开后会启动HTTP服务器,这时电脑端使用浏览器输入
手机的ip,就可以通过web页面的形式访问到这个软件的用户文档。同时在这个web页面里,直接可以进行文件的上传,下载,删除等操作。

下面演示如何开发一个无线U盘,实现功能如下:
1,程序启动后会启动Web服务,并监听设置的端口,等待请求
2,电脑浏览器输入手机ip+端口,在web页上会列出用户文档里所有文件
3,点击文件,即可下载
效果图如下:
详细步骤:
1,这里用到了Swift Taylor(一个用Swift编写HTTP服务器的开发包)。先把Taylor整个包引入到项目。
2,添加个头文件bridge.h,并添加到编译参数里(Taylor内部又使用了一个叫CocoaAsyncSocket的socket库,使用Objective-C写的)
1
#import "GCDAsyncSocket.h"
3,页面代码 ViewController.swift
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
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
import UIKit
import AssetsLibrary
 
class ViewController: UIViewController {
    //文件操作类
    var manager:NSFileManager!
    //保存用户文档目录
    var docPath:NSURL!
     
    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.
         
        //设置用户文档路径
        manager = NSFileManager.defaultManager()
        let urlsForDocDirectory = manager.URLsForDirectory(
            NSSearchPathDirectory.DocumentDirectory,
            inDomains:NSSearchPathDomainMask.UserDomainMask)
        docPath = urlsForDocDirectory[0] as! NSURL
         
        //设置Web服务器
        let server = Server()
        dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), {
            () -> Void in
             
            server.addPostRequestHandler(Middleware.requestLogger(println))
             
            //首页请求
            server.get("/") {
                request, response, callback in
                 
                self.createIndexHtml()
                let file = self.docPath.URLByAppendingPathComponent("index.html")
                let data = self.manager.contentsAtPath(file.path!)
                response.body = data
                callback(.Send(request, response))
            }
             
            //文件请求
            server.get("/file") {
                request, response, callback in
                 
                println(request.arguments)
                var fileName = request.arguments["fileName"]
                let file = self.docPath.URLByAppendingPathComponent(fileName!)
                let data = self.manager.contentsAtPath(file.path!)
                response.body = data
                callback(.Send(request, response))
            }
             
            //启动并监听服务器
            server.startListening(port: 4000, forever: true) {
                result in
                switch result {
                case .Success:
                    println("Up and running")
                case .Error(let e):
                    println("Server start failed \(e)")
                }
            }
        })       
    }
     
    //加载用户文档下的文件,并生成index.html首页
    func createIndexHtml()->Void{
        var content = "<html><meta charset=\"utf-8\"><body>"
        let contentsOfPath = manager.contentsOfDirectoryAtPath(docPath.path!, error: nil)
        for child in contentsOfPath!{
            content = content + "<a target='_blank' href='/file?fileName=\(child)'>\(child)</a><br/>"
        }
        content = content + "</body></html>"
        createFile("index.html", fileBaseUrl: docPath, content:content)
    }
     
    //创建文件
    func createFile(name:String,fileBaseUrl:NSURL,content:String){
        var error:NSErrorPointer = nil
        let file = fileBaseUrl.URLByAppendingPathComponent(name)
        println("文件: \(file)")
        let exist = manager.fileExistsAtPath(file.path!)
        if !exist {
            var error:NSErrorPointer = nil
            manager.removeItemAtPath(file.path!, error:error)
        }
         
        let data = content.dataUsingEncoding(NSUTF8StringEncoding,
            allowLossyConversion: true)
        let createSuccess = manager.createFileAtPath(file.path!,contents:data,
            attributes:nil)
        println("文件创建结果: \(createSuccess)")
    }
     
    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }
}

调试说明:

1,默认使用4000端口,可以在代码里修改

2,真机调试的话,可以先把测试文件用iTunes传到这个APP的用户文档里。再启动程序,电脑输入手机ip+端口访问
3,模拟器调试的话,文件可以直接拷到这个程序的用户文档里(路径在控制台中有打印)。电脑输入localhost+端口访问
4,目前这个只能说是一个只读U盘,有兴趣的可以自行加上文件上传和删除功能。
源码下载:WirelessStorage.zip

Swift - 做一个简单的无线U盘(手机端Http服务器搭建)的更多相关文章

  1. C#做一个简单的进行串口通信的上位机

    C#做一个简单的进行串口通信的上位机   1.上位机与下位机 上位机相当于一个软件系统,可以用于接收数据.控制数据.即可以对接收到的数据直接发送操控命令来操作数据.上位机可以接收下位机的信号.下位机是 ...

  2. 【Bugly干货分享】一起用 HTML5 Canvas 做一个简单又骚气的粒子引擎

    Bugly 技术干货系列内容主要涉及移动开发方向,是由Bugly邀请腾讯内部各位技术大咖,通过日常工作经验的总结以及感悟撰写而成,内容均属原创,转载请标明出处. 前言 好吧,说是“粒子引擎”还是大言不 ...

  3. 使用React并做一个简单的to-do-list

    1. 前言 说到React,我从一年之前就开始试着了解并且看了相关的入门教程,而且还买过一本<React:引领未来的用户界面开发框架 >拜读.React的轻量组件化的思想及其virtual ...

  4. 【 D3.js 入门系列 --- 3 】 做一个简单的图表!

    前面说了几节,都是对文字进行处理,这一节中将用 D3.js 做一个简单的柱形图. 做柱形图有很多种方法,比如用 HTML 的 div 标签,或用 svg . 推荐用 SVG 来做各种图形.SVG 意为 ...

  5. 一起用HTML5 canvas做一个简单又骚气的粒子引擎

    前言 好吧,说是"粒子引擎"还是大言不惭而标题党了,离真正的粒子引擎还有点远.废话少说,先看demo 本文将教会你做一个简单的canvas粒子制造器(下称引擎). 世界观 这个简单 ...

  6. Jmeter初步使用二--使用jmeter做一个简单的性能测试

    经过上一次的初步使用,我们懂得了Jmeter的安装与初步使用的方法.现在,我们使用Jmeter做一个简单的性能测试.该次测试,提交的参数不做参数化处理,Jmeter各元件使用将在介绍在下一博文开始介绍 ...

  7. 用EF DataBase First做一个简单的MVC3报名页面

    使用EF DataBase First做一个简单的MVC3报名网站 ORM(Object Relational Mapping)是面向对象语言中的一种数据访问技术,在ASP.NET中,可以通过ADO. ...

  8. 【 D3.js 入门系列 — 3 】 做一个简单的图表!

    图1. 柱形图 1. 柱形图 前几章的例子,都是对文字进行处理.本章中将用 D3 做一个简单的柱形图.制作柱形图有很多种方法,比如用 HTML 的 <div> 标签,或在 SVG 上绘制 ...

  9. Windows Phone开发(21):做一个简单的绘图板

    原文:Windows Phone开发(21):做一个简单的绘图板 其实我们今天要说的就是一个控件--InkPresenter,这个控件并不是十分强大,没办法和WPF中的InkCanvas相比,估计在实 ...

随机推荐

  1. 【Maven】Missing artifact com.oracle:ojdbc14:jar:10.2.0.4.0

    1.到 http://www.oracle.com/technetwork/database/features/jdbc/index-091264.html 下载你所需要的oraclejar包 2.在 ...

  2. c++ , const对象中的变量不能被修改

    const对象中的变量不能被修改,即使const对象中的函数也不能修改该对象中的变量值 #include <iostream> using namespace std; //------- ...

  3. [Swust OJ 465]--吴奶奶买鱼(0-1背包+dfs)

    题目链接:http://acm.swust.edu.cn/problem/465/ 还有一道题只是描述不一样,方法一模一样(http://acm.swust.edu.cn/problem/644/) ...

  4. BZOJ 2060: [Usaco2010 Nov]Visiting Cows 拜访奶牛( dp )

    树形dp..水 ------------------------------------------------------------------------ #include<cstdio& ...

  5. Irrlicht学习之光照的研究

    Irrlicht学习之光照的研究 最近研究一下Irrlicht的光照.发现Irrlicht的光照还是比较简单的,相比低于它的OpenGL和Direct3D,设置光源以及设置光照的参数更加人性化(可能是 ...

  6. yii_wiki_145_yii-cjuidialog-for-create-new-model (通过CJuiDialog来创建新的Model)

    /**** CJuiDialog for create new model http://www.yiiframework.com/wiki/145/cjuidialog-for-create-new ...

  7. 设计模式(六)桥连模式Bridge(结构型)

      设计模式(六)桥连模式Bridge(结构型) 1. 概述 在软件系统中,某些类型由于自身的逻辑,它具有两个或多个维度的变化,那么如何应对这种“多维度的变化”?如何利用面向对象的技术来使得该类型能够 ...

  8. Python标准库:内置函数repr(object)

    本函数是返回对象object的具体说明字符串. 样例: #repr() print(repr(range(5))) print(repr(help)) print(repr(0x200)) print ...

  9. ioc构架demo

    1.视图 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:too ...

  10. assert()用法

    assert宏的原型定义在<assert.h>中,其作用是如果它的条件返回错误,则终止程序执行,原型定义:[1] #include <assert.h>void assert( ...