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])
    }


}

2018-04-16 10:40:22 amberoot 阅读数 279

//把字符串写进文件,文件保存在沙盒中Documents路径中

func writeStrToFile(receivedString: NSString) {        

    let str = receivedString as String

    let wr = NSMutableData()

   wr.append(str.data(using:String.Encoding(rawValue: String.Encoding.utf8.rawValue))!)

 

    let manager = FileManager.default

    let urlsForDocDirectory = manager.urls(for:.documentDirectory, in:.userDomainMask)

    let docPath = urlsForDocDirectory[0]

    let file = docPath.appendingPathComponent("Demo.txt")//若不存在该文件,则自动创建

    let writeHandler = try? FileHandle(forWritingTo:file)

    if writeHandler != nil {

         writeHandler!.seekToEndOfFile()

         writeHandler?.write(wr as Data)

    }

        

        

}

 

2017-06-08 22:20:11 mft8899 阅读数 303

 ----- 存入 APP 的目录 Documents 中  ------

 

        let urlStr = NSURL(string: "http://images.macx.cn/forum/201301/18/061737r4zfhs4bsrkrnrsq.jpg")
        let data = NSData(contentsOf: urlStr! as URL)
        //如果没有图片
        if(data == nil){
            print("no img")
            return;
        }
        let image = UIImage(data: data! as Data)
        //要写入的文件夹路径和图片名
        let dt:String = NSHomeDirectory().appending("/Documents/").appending("2.png") as String;
        /*打印路径: 可通过 finder 然后 快捷键 ctrl+shift+g 前往文件夹功能 进入 如下文件夹
         /Users/admin/Library/Developer/CoreSimulator/Devices/8C4DA6F7-4431-402A-92A9-E83087F5159D/data/Containers/Data/Application/4935114D-926D-4EDA-918D-FA14EE023A34/Documents/2.png
        */
        //将Image文件写入 如上的文件夹
        try? UIImagePNGRepresentation(image!)?.write(to: URL(fileURLWithPath: dt))
        
        
        //读取 文件夹 中 的 图片
        let img2 = UIImage(contentsOfFile: dt)
        //如果没有找到本地图片
        if(img2 == nil){
            print("not find local img")
            return;
        }
        let imageView = UIImageView(image: img2)
        imageView.contentMode = .center
        imageView.frame = CGRect(x: 0, y: 0, width: 400, height: 200);
        imageView.backgroundColor = UIColor.blue
        self.view.addSubview(imageView)
        

 

本地的HTML 读取 以上存入的图片 

//获取Documents在本机的路径
let docu:String = NSSearchPathForDirectoriesInDomains(FileManager.SearchPathDirectory.documentDirectory, FileManager.SearchPathDomainMask.userDomainMask, true)[0];       

//向HTML注入JS 改变图片的src
wkwebview.evaluateJavaScript("document.getElementById('ffee').setAttribute('src','file://"+docu+"/3g.163.com_big.png');");

 

 

---------存入相册 -------

在 info.plist 中添加权限

Privacy - Photo Library Usage Description 



 

 

        let image = UIImage(data: data! as Data)
        UIImageWriteToSavedPhotosAlbum(image!, nil, nil, nil)
 

 --------- 存入剪贴板 --------

        let image = UIImage(data: data! as Data)
        UIPasteboard.general.image = image

 

 

 

2017-01-02 22:33:07 NoPolun_iOS 阅读数 388

一、 字符串存储

let str = "Hello, World!"

//第一个参数是转化成编码的格式,第二个参数是在编码过程中是否允许删减或替换

let utf8Str = str.data(using: String.Encoding.utf8, allowLossyConversion: true)

二、初始化方法

1 、let withd = NSData(data:utf8Str!)


2、let url = NSURL(string:"https:baidu.com")
      let withURL = NSData.init(contentsOf: url as! URL)
      print(withURL!)

3、let file = Bundle.main.path(forResource: "text", ofType: "plist")
      let withPath = NSData.init(contentsOfFile: file!)

三、访问数据

 1、let utf8Str = str.data(using: String.Encoding.utf8, allowLossyConversion: true)

       let des = utf8Str?.description

 2、详细信息

   let utf8Str: NSData! = str.data(using: String.Encoding.utf8, allowLossyConversion: true) as NSData!
   var bytes = utf8Str.bytes
   var string = NSString.init(bytes: bytes, length: utf8Str.length, encoding: String.Encoding.utf8.rawValue)
   print(string!)

四、字节数据存储

   let strPath = "所要存储的信息"
   let utf8data:NSData! = strPath.data(using: String.Encoding.utf8, allowLossyConversion: true) as NSData!
   var pathArray = NSSearchPathForDirectoriesInDomains(FileManager.SearchPathDirectory.documentDirectory, FileManager.SearchPathDomainMask.userDomainMask, true)

   let defaultPath = pathArray[0]
   let  textpath = defaultPath + "/text.txt"
   print(textpath)
   let  result = utf8data.write(toFile: strPath, atomically: true)

   //数据的读取

let datas = NSData.init(contentsOfFile: textpath)
let utf8Str = NSString.init(data: datas as! Data, encoding: String.Encoding.utf8.rawValue)
print(utf8Str!)

   /**********************/ 访问路径方法

   let path = Bundle.main.path(forResource: "text", ofType: "txt")

   /************/

2016-06-16 10:50:05 jjblockAndmm 阅读数 722

整数

swift 提供了8, 16, 32, 64位的有符号和无符号整数类型.类似 C语言的命名方式,比如8位无符号整数类型就是UInt8,32位有符号整数类型就是Int32.就像 swift 的其他类型一样,整数类型采用大写命名法.

整数范围

如果想获取对应类型的最大值和最小值,也是很方便的.
let min = UInt8.min // min 为0,是 UInt8类型
let max = UInt8.max // max 为255

Int

一般来说,不需要专门指定整数的长度, swift提供了一个特殊的整数类型Int,长度与当前平台的原生字长相同:
在32位平台上IntInt32长度相同.
在64位平台上IntInt64长度相同.
除非你需要特定长度的整数,一般来说使用Int就够了.这可以提高代码的一致性和可复用性.即使是在32位平台上,Int可以存储的整数范围也可以达到-2,147,483,648~2,147,483,647,这个数已经够大了.

UInt

swift 也提供了一个特殊的无符号类型哦,长度与当前平台的原生字长相同.
大家尽量不要使用UInt,除非你真想要存储一个和当前平台原生字长相同的无符号整数.出了这种情况,最好使用Int,即使你要存储的值已知是非负的.统一使用Int 可以提高代码的复用性,避免不同类型数字之间的转换,并且匹配数字的类型推断.

浮点数

浮点数大家都知道,就是有小数部分的数字.比如3.1415926,-2.3442332.
浮点类型比整数类型表示的范围更大,可以存储比Int类型更大或者更小的数字.swift 提供了两种有符号浮点数类型:
Double表示64位浮点数,当你需要存储很大或者很高精度的浮点数时请使用此类型.
Float表示32位浮点数.精度要求不高的话可以使用此类型.
选择哪个类型取决于你的代码需要处理的值的范围.

类型安全和类型推断

swift 是一个类型安全的语言.类型安全的语言可以让你清楚地知道代码要处理值的类型.如果你的代码需要一个 string,你千万不要传一个 int.
由于 swift是类型安全的,所以它会在编译你的代码时进行类型检查,并把不匹配的类型标记为错误,这可以让你在开发过程中尽早发现并修复错误.
当你要处理不同类型的值时,类型检查可以帮你避开错误.然而,这并不是说你每次声明常量和变量的时候都需要显式指定类型,如果你没有指定类型, swift会使用类型推断来选择合适的类型.有了类型推断,编译器可以在编译代码的时候自动推断出表达式的类型.原理很简单,只要检查你赋的值即可.
因为有类型推断,和 C或者 Objective-C 比起来 swift很少需要声明类型.常量和变量虽然需要明确的类型,但是大部分工作并不需要程序员来完成.
当你声明常量或者变量并赋初值的时候类型推断非常有用.当你在声明常量或者变量的时候赋给它们一个字面量(literal value)即可触发类型推断.字面量就是会直接出现在你代码中的值,如449.8678
如果你给一个新常量赋值42并且没有标明类型, swift 可以推断出常量类型是Int,因为你给它赋的初始值是个整数.
let value = 44 //value 会被推断为 Int类型
同样的,其他类型也是可以推断出来的,这里不再赘述.

数值型字面常量

整数字面量可以被写作 :
- 一个十进制数没有前缀
- 一个二进制数,前缀是0b
- 一个八进制数,前缀是0o
- 一个十六进制数,前缀是0x
下面列举的所有整数字面量的十进制值都是16:
let d = 16
let b = 0b10000 // 二进制的16
let o = 0o20 // 八进制的16
let h = 0x10 // 十六进制的16

浮点字面量可以是十进制(没有前缀)或者是十六进制(前缀是0x).小数点两边必须有至少一个十进制数字(或者是十六进制的数字).浮点字面量还有一个可选的指数(exponent),在十进制浮点数中通过大写或者小写 e 来指定,在十六进制浮点数中通过大写或者小写的 p 来指定.
如果一个十进制数的指数为 exp,那这个数相当于基数和10^exp 的乘积
*1.25e2表示1.25x10^2,等于125.0.
*1.25e-2表示1.25x10^-2,等于0.0125.
如果一个十六进制数的指数为 exp,那这个数相当于基数和2^exp 的乘积
*0xFp2表示15x2^2,等于60.0
*0xFp-2表示15x2^-1等于3.75
数值类型字面变量可以包括额外的格式来增强可读性.整数和浮点数都可以添加额外的0并且包涵下划线,并不会影响字面量:
let p = 00001122.2334
let m = 1_000_000
let n = 1_000_000.000_000_002

数值类型转换

即使代码中的整数常量和变量已知非负数,也最好使用Int类型.总是使用默认的整数类型可以保证你的整数常量和变量可以直接被复用并且可以匹配整数类字面量的类型推断.
只有在必要的时候才使用其他整数类型,比如要处理外部的长度明确的数据或者为了优化性能.使用显式指定长度的类型可以及时发现值溢出并且可以暗示正在处理的特殊数据.

整数转换

不同整数类型的变量和常量可以存储不同范围的数字.Int8类型的常量或者变量可以存储的数字范围是-128~127,而UInt8类型的常量或者变量能存储的数字范围是0~255.如果数字超出了常量或者变量的可存储范围,编译时就会报错.

let a:UInt8 = -1 // UInt8类型不能存负数,此时会报错
let abigValue:Int8 = Int8.max + 1 // Int8类型不能存储超过其最大值的数,此时会报错

由于每种整数类型都可以存储不同范围的值,所以你必须根据不同的情况选择性使用数值型类型转换.这种选择性使用的方式,可以预防隐式转换的错误并让你的代码中的类型转换意图变得清晰.
要将一种数字类型转换成另一种,你要用当前值来初始化一个期望类型的新数字,这个数字的类型就是你的目标类型.在下面的例子中,常量aUInt16类型,然而常量b是一个UInt8类型.它们不能直接相加,因为它们类型不同.所以要调用UInt16(b)来创建一个新的UInt16数字并用b 的值来初始化,然后使用这个新数字来计算:
let a:UInt16 = 1_000
let b:UInt8 = 1
let ab = a + UInt16(b)

现在两个数字的类型都是UInt16,可以进行相加.目标常量ab 的类型被推断为UInt16,因为它是两个UInt16值的和.

整数和浮点数转换

整数和浮点数的转换必须是显式指定类型
let a = 3
let b = 0.23
let ab = Double(a) + b //ab 等于3.23 ,所以被推测为 Double 类型

浮点数到整数的反向转换同样可以,这里不再赘述.
结合数字类常量和变量不同于结合数字类字面量.字面量3可以直接和字面量0.13相加,因为数字字面量本身没有明确的类型,它们的类型只在编译器需要求值的时候被推测.

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