Fork me on GitHub

使用Swift后端框架Perfect做一个文件上传服务器

最近App总有些奇奇怪怪的偶现bug,测试同学不堪其扰,需要我们尽快排查,iOS查看日志没有安卓那么方便,又不想被满屏的NSLog(有些第三方库打印超多日志)遮挡视线,好在我们集成了CocoaLumberjack,可以用它将记录下来存入文件,然后查看或导出,最初的想法是直接做个日志管理的界面,用个textView展示日志,但是发现用的次数多了之后,日志量猛增,在手机这种小屏幕上查看效率堪忧,还是放在电脑上,字体大小随便调,更有搜索这种神器级别的功能,查找bug不是梦。

但是每次导出文件还要连接电脑,好麻烦,于是幻想能无线传输该多好,测试同学发现问题,直接点击一键上传日志,然后。

正好一直想用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
private func uploadHandler(request: HTTPRequest, response: HTTPResponse) {

// create uploads dir to store files
let fileDir = Dir(Dir.workingDir.path + "files")
do {
try fileDir.create()
} catch {
print(error)
}

var code = 400

// Grab the fileUploads array and see what's there
// If this POST was not multi-part, then this array will be empty

if let uploads = request.postFileUploads, uploads.count > 0 {
// Create an array of dictionaries which will show what was uploaded
var ary = [[String:Any]]()

for upload in uploads {
ary.append([
"fieldName": upload.fieldName,
"fieldValue": upload.fieldValue
])

if upload.tmpFileName.count == 0 {
continue
}

// move file
let thisFile = File(upload.tmpFileName)
do {

let _ = try thisFile.moveTo(path: fileDir.path + upload.fieldName, overWrite: true)
print("upload file success: \(upload.fieldName)")
code = 200

} catch {
print(error)
}
}

do {

let data = try JSONSerialization.data(withJSONObject: ary, options: JSONSerialization.WritingOptions.prettyPrinted)
let strJson = String.init(data: data, encoding: .utf8)

Log.info(message: strJson!)
} catch {
Log.info(message: "\(error)")
}
}

let dict = [ "code": "\(code)", "msg": "success" ]

do {
try response.setBody(json: dict)
} catch {
print("response error: \(error)")
}

response.completed(status: .ok)
}

客户端代码:

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
- (void)uploadLogFilesToUrl:(NSString *)url completeBlock:(void (^)(void))completeBlock {

kWeakSelf(self);

NSString *path = self.logPath;
NSString *fileName = self.logName;

if (fileName) {

NSString *filePath = [path stringByAppendingPathComponent:fileName];
NSDictionary *tmpDic = [WVRAppModel sharedInstance].commenParams;
NSMutableDictionary *muDict = [NSMutableDictionary dictionaryWithDictionary:tmpDic];
muDict[@"deviceId"] = [WVRUserModel sharedInstance].deviceId;
muDict[@"fileList"] = self.logList;
muDict[@"buildVer"] = kBuildVersion;
muDict[@"deviceModel"] = [WVRDeviceModel deviceModel];

NSString *logName = [NSString stringWithFormat:@"%@_%@_%@", muDict[@"deviceModel"], muDict[@"deviceId"], [NSDate chinaDate]];

AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];
[manager POST:url parameters:muDict constructingBodyWithBlock:^(id<AFMultipartFormData> _Nonnull formData) {

[formData appendPartWithFileData:[NSData dataWithContentsOfFile:filePath] name:logName fileName:fileName mimeType:@"text/plain"];

} progress:^(NSProgress * _Nonnull uploadProgress) {

} success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) {

if (completeBlock) {
completeBlock();
}
} failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {

NSLog(@"%@", error);
}];
}
}

之后有空了,还可以研究以下使用Perfect后端进行APNS消息推送。这样有日志上传好之后,就可以收到消息推送,再也不用去翻看文件夹或者盯着控制台日志啦。

------------- 本文结束感谢您的阅读 -------------