背景
最近遇到一個Bug,在用AFNetworking下載下傳檔案的時候莫名其妙的失敗了,跟了一下發現一個小坑,記錄一下防止以後再掉進去。
iOS和Linux的檔案名的長度限制相同都是255個字元!!!
問題根源是檔案名超度超過了255個字元,AFNetworking下載下傳檔案是成功了(架構會把檔案下載下傳到一個臨時檔案,例如:
CFNetworkDownload_xxx.tmp
,這個檔案名不會出現過長的問題),下載下傳成功之後會copy到調用者指定路徑,在這裡指定的檔案名超過了255個字元,導緻建立檔案失敗,于是回調是成功了,但是在設定的路徑找不到這個檔案。
上代碼!
下載下傳代碼:
// 注意對檔案名長度進行處理!!!
NSString *destination = @"下載下傳位址(長度大于255)";
NSURLSessionDownloadTask *aTask = [self.updownloadSessionManager downloadTaskWithRequest:mutableRequest progress:^(NSProgress * _Nonnull downloadProgress) {
} destination:^NSURL * _Nonnull(NSURL * _Nonnull targetPath, NSURLResponse * _Nonnull response) {
return [NSURL fileURLWithPath:destination];
} completionHandler:^(NSURLResponse * _Nonnull response, NSURL * _Nullable filePath, NSError * _Nullable error) {
// 下載下傳成功後會回調該block,但是路徑`destination`找不到這個檔案
}];
[aTask resume];
出錯的地方AFURLSessionManager.m
- (void)URLSession:(NSURLSession *)session
downloadTask:(NSURLSessionDownloadTask *)downloadTask
didFinishDownloadingToURL:(NSURL *)location
{
self.downloadFileURL = nil;
if (self.downloadTaskDidFinishDownloading) {
self.downloadFileURL = self.downloadTaskDidFinishDownloading(session, downloadTask, location);
if (self.downloadFileURL) {
NSError *fileManagerError = nil;
// location是臨時檔案,是下載下傳成功了
// self.downloadFileURL 是目标路徑,檔案名超過255
// 移動檔案會報錯
if (![[NSFileManager defaultManager] moveItemAtURL:location toURL:self.downloadFileURL error:&fileManagerError]) {
// 出錯會發通知,可以監聽處理
[[NSNotificationCenter defaultCenter] postNotificationName:AFURLSessionDownloadTaskDidFailToMoveFileNotification object:downloadTask userInfo:fileManagerError.userInfo];
}
}
}
}
我們來看看
AFURLSessionDownloadTaskDidFailToMoveFileNotification
的定義
AFURLSessionManager.h
/**
Posted when a session download task encountered an error when moving the temporary download file to a specified destination.
*/
FOUNDATION_EXPORT NSString * const AFURLSessionDownloadTaskDidFailToMoveFileNotification;