天天看點

AFNetworking下載下傳檔案時檔案名長度的坑

背景

最近遇到一個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;
           

繼續閱讀