Swift: загрузкаTaskWithURL иногда завершается успешно с ненулевым местоположением, даже если файл не существует

Функция downloadTaskWithURL иногда возвращает ненулевое местоположение для несуществующего файла.

В тестовой среде нет файла по адресу http://192.168.0.102:3000/p/1461224691.mp4.

В большинстве случаев вызов downloadTaskWithURL для этого URL-адреса приводит к ожидаемому сообщению об ошибке:

Ошибка загрузки сообщения при работе в сети. URL-адрес загрузки: http://192.168.0.102:3000/p/1461224691.mp4. Местонахождение: нет. Ошибка: необязательно (домен ошибки = код NSURLErrorDomain = -1100 «Запрошенный URL-адрес не найден на этом сервере». " rel="nofollow">http://192.168.0.102:3000/p/1461224691.mp4, NSLocalizedDescription=Запрашиваемый URL не найден на этом сервере., NSErrorFailingURLStringKey=http://192.168.0.102:3000/p/1461224691.mp4})

Иногда и недетерминированным образом downloadTaskWithURL считает, что файл существует, и записывает что-то в переменную location. В результате сторожевое условие не срабатывает, а код продолжает выполняться... чего не должен.

Постоянный файл, созданный fileManager.moveItemAtURL(location!, toURL: fileURL), имеет размер всего 1 байт, что подтверждает, что сетевой файл никогда не существовал.

Почему downloadTaskWithURL так себя ведет?

func download() {
    // Verify <networkURL>
    guard let downloadURL = NSURL(string: networkURL) where !networkURL.isEmpty else {
        print("Error downloading message: invalid download URL. URL: \(networkURL)")
        return
    }

    // Generate filename for storing locally
    let suffix = (networkURL as NSString).pathExtension
    let localFilename = getUniqueFilename("." + suffix)

    // Create download request
    let task = NSURLSession.sharedSession().downloadTaskWithURL(downloadURL) { location, response, error in
        guard location != nil && error == nil else {
            print("Error downloading message during network operation. Download URL: \(downloadURL). Location: \(location). Error: \(error)")
            return
        }

        // If here, no errors so save message to permanent location
        let fileManager = NSFileManager.defaultManager()
        do {
            let documents = try fileManager.URLForDirectory(.DocumentDirectory, inDomain: .UserDomainMask, appropriateForURL: nil, create: false)
            let fileURL = documents.URLByAppendingPathComponent(localFilename)
            try fileManager.moveItemAtURL(location!, toURL: fileURL)
            self.doFileDownloaded(fileURL, localFilename: localFilename)
            print("Downloaded file @ \(localFilename). Download URL: \(downloadURL)")
        } catch {
            print("Error downloading message during save operation. Network URL: \(self.networkURL). Filename: \(localFilename). Error: \(error)")
        }
    }

    // Start download
    print("Starting download @ \(downloadURL)")
    task.resume()
}

person Crashalot    schedule 23.04.2016    source источник


Ответы (1)


Просто чтобы уточнить, сервер возвращает 404, но задача загрузки возвращает практически пустой файл? И вы уверены, что сервер действительно вернул код ошибки (проверив журналы сервера)?

В любом случае, я бы предложил проверить код состояния в объекте ответа. Если это не 200, то задача загрузки, вероятно, только что загрузила тело ответа страницы с ошибкой. Или, если код состояния равен 0, время ожидания соединения истекло. В любом случае, считайте это неудачей.

Вы также можете попробовать заставить все это происходить в одном потоке и посмотреть, исчезнет ли недетерминизм.

person dgatwood    schedule 01.05.2016
comment
спасибо, хорошие идеи. попробую их и сообщу о результатах! - person Crashalot; 01.05.2016