2020-01-15 16:16:35 ZY_FlyWay 阅读数 29

背景:

  • 服务器端通过接口返回word文档base64编码字符串
  • 客户端需求是缓存预览分享等

 

处理思路

  1. 请求接口下载base64字符串
  2. base64解码转成Data
  3. 在 Document创建文件夹,在文件夹下创建文件
  4. 将Data写入文件
  5. 使用QuickLook预览,展示。
     

下载和文件代码


//  下载文件类
//  LoadFilesManager.swift
//  NVRCloudIOS
//
//  Created by Nvr on 2018/12/28.
//  Copyright © 2018 zhangyu. All rights reserved.
//

import UIKit
import Alamofire
import MBProgressHUD
import SwiftyJSON

class LoadFilesManager: NSObject {

    static let shared = LoadFilesManager()
    let filesManager = FileManager.default

    //创建文件夹的根目录
    var rootPath:URL?{
        return filesManager.urls(for: .documentDirectory, in: .userDomainMask).first
    }

    //下载合同
    func loadContract(contractNo:String,callBack:@escaping UpdateCallBack) {

        let progressHud = MBProgressHUD.showAdded(to: UIApplication.shared.keyWindow!, animated: true)
        progressHud.mode = .annularDeterminate
        progressHud.label.text = "下载中..."
        if let path = rootPath {
            //如果存在文件夹,创建文件
            if createFolder(name: "Contract", baseUrl: path as NSURL){
                let result = creatFlie(fliesName: "/Contract/\(contractNo).docx")
                if result.0{
                    let urlString = String(format: GlobalConfig.RentalPath.downLoadContract,contractNo)
                    guard let url = URL(string: urlString) else{
                        return
                    }
                    restApiService.setAlamofireHeader(contentType: ContentType.JSON, url: urlString)
                    let request = Alamofire.request(url, method: .get, parameters: nil, encoding: JSONEncoding.default, headers: header)
                    request.downloadProgress(closure: { (progress) in
                        progressHud.progressObject = progress
                    }).responseJSON { (respons) in
                        DispatchQueue.main.async {
                            progressHud.hide(animated: true)
                        }
                        switch respons.result {
                        case .success(let value):
                            guard let docString = JSON(value)["result"].string else{
                                return
                            }
                            do {
                                let base64Data = Data.init(base64Encoded: docString, options: [])
                                try base64Data?.write(to: URL(fileURLWithPath: result.1))
                                callBack()
                            }catch{
                                NVRLOG("写入失败")
                            }
                        case .failure:
                            break
                        }
                    }
                }
            }
        }
    }

}

//文件操作相关
extension LoadFilesManager{

    //创建文件夹
    func createFolder(name:String,baseUrl:NSURL) -> Bool{
        do {
            if let folder = baseUrl.appendingPathComponent(name, isDirectory: true){
                let exist = filesManager.fileExists(atPath: folder.path)
                if !exist {
                    try filesManager.createDirectory(at: folder, withIntermediateDirectories: true,
                                                 attributes: nil)
                }
                return true
            }
            return false
        }catch{
            NVRLOG("创建失败")
            return false
        }
    }

    //创建文件
    func creatFlie(fliesName:String) -> (Bool,String){
        guard let rootPath = rootPath?.path else {
            return (false,"")
        }
        let path = rootPath + fliesName
        let exist = filesManager.fileExists(atPath: path)
        if !exist{
            if filesManager.createFile(atPath: path, contents: nil, attributes: nil){
                NVRLOG("文件创建成功")
                return (true,path)
            }else{
                NVRLOG("创建失败")
                return (false,path)
            }
        }
        return (true,path)
    }

    //判断文件是否存在
    func existDownLoadContract(contractNo:String) -> Bool{
        guard let rootPath = rootPath?.path else {
            return false
        }
        let path = rootPath + "/Contract/\(contractNo).docx"
        let exist = filesManager.fileExists(atPath: path)
        return exist
    }

    //获取Document文件夹下所有文件
    func getFilesInFolder(subPath:String) -> [String]{
        guard let rootPath = rootPath?.path else {
            return []
        }
        let path = rootPath + "/Contract/"
        let dirEnum = filesManager.enumerator(atPath: path)
        var contractNoPaths = [String]()
        while let file = dirEnum?.nextObject() as? String{
            if file.hasSuffix(".docx") || file.hasSuffix(".doc"){
                contractNoPaths.append(path+file)
            }
        }
        return contractNoPaths
    }
}

预览相关代码


//
//  ContractDetailViewController+QuickLook.swift
//  NVRCloudIOS
//
//  Created by Nvr on 2018/12/29.
//  Copyright © 2018 zhangyu. All rights reserved.
//

import Foundation
import QuickLook


extension ContactDetailViewController:QLPreviewControllerDelegate,QLPreviewControllerDataSource{

    func jumpToQuickLook(contractNo:String){
        allDownLoadsContract = LoadFilesManager.shared.getFilesInFolder(subPath: "/Contract")
        var currentIndex = 0
        guard let list = allDownLoadsContract else{
            return
        }
        for (index,filePath) in list.enumerated() {
            if filePath.contains(contractNo){
                currentIndex = index
            }
        }
        let qlVc = QLPreviewController.init()
        qlVc.delegate = self
        qlVc.dataSource = self
        qlVc.currentPreviewItemIndex = currentIndex
        self.navigationController?.pushViewController(qlVc, animated: true)
    }


    func numberOfPreviewItems(in controller: QLPreviewController) -> Int {
        return allDownLoadsContract?.count ?? 0
    }

    func previewController(_ controller: QLPreviewController, previewItemAt index: Int) -> QLPreviewItem {
        guard let list = allDownLoadsContract else{
            return NSURL(fileURLWithPath:"")
        }
        return NSURL(fileURLWithPath: list[index])
    }


}

2017-07-06 16:59:37 robinson_911 阅读数 1149


1. data 根据url这个key存储在 fetchLoads中

// A single key may have multiple callbacks. Only download once.
    func setup(progressBlock: ImageDownloaderProgressBlock?, with completionHandler: ImageDownloaderCompletionHandler?, for url: URL, options: KingfisherOptionsInfo?, started: ((URLSession, ImageFetchLoad) -> Void)) {

        barrierQueue.sync(flags: .barrier) {
            let loadObjectForURL = fetchLoads[url] ?? ImageFetchLoad()
            let callbackPair = (progressBlock: progressBlock, completionHandler: completionHandler)
            
            loadObjectForURL.contents.append((callbackPair, options ?? KingfisherEmptyOptionsInfo))
            
            //data 根据url这个key存储在 fetchLoads中
            fetchLoads[url] = loadObjectForURL
            
            if let session = session {
                started(session, loadObjectForURL)
            }
        }
    }

2. 获取每次网络传输过来的数据
  func urlSession(_ session: URLSession, dataTask: URLSessionDataTask, didReceive data: Data) {

        print("Data......\(data)")
        guard let downloader = downloadHolder else {
            return
        }

        if let url = dataTask.originalRequest?.url, let fetchLoad = downloader.fetchLoad(for: url) {

        1.将获取的数据data放到downloadHolder.fetchLoad (此处的downloader和downloadHolder是同一块内存地址,所以给downloader拼接获取的网络数据,就相当于给downloadHolder拼接数据)中去。
               2.downloadHolder为全局变量,以便于后面获取数据完毕后,可以根据url来取data

           fetchLoad.responseData.append(data) //存储每次获取的数据
       }

3. 网络数据获取完毕,进行图片解码,图片缓存到本地
    //图片数据加载完毕,进入此回调方法
    func urlSession(_ session: URLSession, task: URLSessionTask, didCompleteWithError error: Error?) {
        
        guard let url = task.originalRequest?.url else {
            retur
        }
        
        guard error == nil else {
            callCompletionHandlerFailure(error: error!, url: url)
            return
        }
        //数据请求完,在此处完成completionHandler 回调
               //在这个函数中,根据url去downloadHolder取image 的data数据,然后解码,存储。
         processImage(for: task, url: url)     
   }

4. data数据处理成image的方法

    //数据请求完,在此处完成completionHandler 回调
    //对于每一张根据URL取出来的data,在此做图片的预处理。
    //当选择图片的默认处理方式时,var image = imageCache[processor.identifier]中的
    //processor.identifier = ""处理,具体看identifier的定义说明
    private func processImage(for task: URLSessionTask, url: URL) {

        guard let downloader = downloadHolder else {
            return
        }
        
        // We are on main queue when receiving this.
        downloader.processQueue.async {
            
            guard let fetchLoad = downloader.fetchLoad(for: url) else {
                return
            }
            
            self.cleanFetchLoad(for: url)
            
            let data = fetchLoad.responseData as Data
            
            // Cache the processed images. So we do not need to re-process the image if using the same processor.
            // Key is the identifier of processor.
            var imageCache: [String: Image] = [:]
            for content in fetchLoad.contents {
                
                let options = content.options
                let completionHandler = content.callback.completionHandler
                let callbackQueue = options.callbackDispatchQueue
                
                let processor = options.processor
                
                var image = imageCache[processor.identifier]
                if image == nil {
                    image = processor.process(item: .data(data), options: options)
                    
                    // Add the processed image to cache. 
                    // If `image` is nil, nothing will happen (since the key is not existing before).
                    imageCache[processor.identifier] = image
                }
                
                if let image = image {
                    
                    downloader.delegate?.imageDownloader(downloader, didDownload: image, for: url, with: task.response)
                    
                    if options.backgroundDecode {
                        let decodedImage = image.kf.decoded(scale: options.scaleFactor)
                        callbackQueue.safeAsync { completionHandler?(decodedImage, nil, url, data) }
                    } else {
                        callbackQueue.safeAsync { completionHandler?(image, nil, url, data) }
                    }
                    
                } else {
                    if let res = task.response as? HTTPURLResponse , res.statusCode == 304 {
                        let notModified = NSError(domain: KingfisherErrorDomain, code: KingfisherError.notModified.rawValue, userInfo: nil)
                        
                        //数据请求完,在此处完成completionHandler 回调
                        completionHandler?(nil, notModified, url, nil)
                        continue
                    }
                    
                    let badData = NSError(domain: KingfisherErrorDomain, code: KingfisherError.badData.rawValue, userInfo: nil)
                    callbackQueue.safeAsync { completionHandler?(nil, badData, url, nil) }
                }
            }
        }
    }
}



2017-12-06 18:40:25 mingmingsuper 阅读数 415
今天有一个需求需要做到数组中有一条数据一定要排在第一个,刚开始的写法是将这条数据取出来缓存一下,然后将这条数据插入到已经排除掉这条数据的数组中的第一个,代码如下:

let id = "aaa"
let first = self.fullDatas?.filter({ (data) -> Bool in
            if id == data.doctorid {
                return true
            }
            return false
        }).first
        var datas = self.fullDatas?.filter({ (data) -> Bool in
            if id != data.doctorid {
                return true
            }
            return false
        })
        datas?.insert(first!, at: 0)
最后这个datas就是我们要的结果,这种写法看起来很傻,后来我就思考是不是需要用排序来搞定这个问题,做了尝试结果很满意,同样达到了想要的结果,代码如下

let list = fullDatas.sorted(by: { (data1, data2) -> Bool in if id == data.id { return true } return false }) //哈哈实现啦


查看原文:https://www.liuandy.cn/ios/swift%e6%95%b0%e7%bb%84%e4%b8%ad%e4%b8%80%e6%9d%a1%e6%95%b0%e6%8d%ae%e7%bd%ae%e9%a1%b6%e3%80%90%e5%8e%9f%e5%88%9b%e3%80%91.html
2017-10-18 18:31:36 mqz1228 阅读数 2348
  • AlamofireCache的封装实现对网络数据的缓存,可以存储JSON、String、Data,接口简单明了.
  • 封装Alamofire下载,使用更方便.
  • 如有问题,欢迎提出,不足之处,欢迎纠正,欢迎star ✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨
  • Github: https://github.com/MQZHot/DaisyNet
    缓存.gif

下载.gif

1. 请求+缓存

  • 缓存数据只需要调用.cache(true),不调用或者.cache(false)则不缓存
  • 调用responseCacheAndString可以先读取缓存数据,再读取网络数据
  • 通过isCacheData属性可以区分缓存数据还是网络数据
DaisyNet.request(url, params: params).cache(true).responseCacheAndJson { value in
    switch value.result {
    case .success(let json):
        if value.isCacheData {
            print("我是缓存的")
        } else {
            print("我是网络的")
        }
    case .failure(let error):
        print(error)
    }
}
  • 你也可以分别读取缓存数据和网络数据,如下代码
  • 调用cacheJson方法获取缓存数据,调用responseJson获取网络数据
DaisyNet.request(url, params: params).cache(true).cacheJson { json in
        print("我是缓存的")
    }.responseJson { response in
    print("我是网络的")
}
  • 如果你不需要缓存,可以直接调用responseJson方法
DaisyNet.request(url).responseString { response in
    switch response {
    case .success(let value): print(value)
    case .failure(let error): print(error)
    }
}
  • 同理,如果你要缓存Data或者String,与JSON是相似的
/// 先读取缓存,再读取网络数据
DaisyNet.request(url).cache(true).responseCacheAndString { value in }
DaisyNet.request(url).cache(true).responseCacheAndData { value in }
/// 分别获取缓存和网络数据
DaisyNet.request(url).cache(true).cacheString { string in
        print("我是缓存的")
    }.responseString { response in
    print("我是网络的")
}
  • 取消请求
DaisyNet.cancel(url, params: params)
  • 清除缓存
/// 清除所有缓存
func removeAllCache(completion: @escaping (Bool)->())
/// 根据url和params清除缓存
func removeObjectCache(_ url: String, params: [String: Any]? = nil, completion: @escaping (Bool)->())

2. 下载

思路:
  • 1.下载中的任务,用url作为key添加到DownloadManager单例中
  • 2.取消任务、删除任务以及下载失败时,将下载任务从单例中删除,保证- DownloadManager单例的downloadTasks中是正在下载的
  • 3.暂停下载,保存已经下载的data到plist文件
DaisyNet.download(url).downloadProgress { progress in
        /// 下载进度
    }.response { response in
    /// 下载完成
}
  • 如果正在下载中退出当前界面,再次进入时可以通过以下方法获取下载进度,并改变UI
DaisyNet.downloadProgress(url) {
        print($0)
    }?.response(completion: { _ in
    print("下载完成")
})
  • 获取下载状态
DaisyNet.downloadStatus(url)
  • 获取下载百分比
DaisyNet.downloadPercent(url)
  • 获取下载完成后文件所在位置
DDaisyNet.downloadFilePath(url)
  • 删除某个下载
DaisyNet.downloadDelete(url)
  • 取消某个下载
DaisyNet.downloadCancel(url)
2014-08-28 09:51:13 gaoyp 阅读数 7773
#import "SDWebImageManager.h"
#import "SDImageCache.h"


NSString* strUrl = @"http://xxx.com/x.jpg";
SDWebImageManager *manager = [SDWebImageManager sharedManager];
NSString* key = [manager cacheKeyForURL:[NSURL URLWithString:strUrl]];
SDImageCache* cache = [SDImageCache sharedImageCache];
//此方法会先从memory中取。
image = [cache imageFromDiskCacheForKey:key];

Swift # 沙盒缓存

阅读数 8

数据存储NSData

阅读数 388

没有更多推荐了,返回首页