zoukankan      html  css  js  c++  java
  • Hbuilder打包H5开发的App读取写入手机本地文件

    在平时开发的html页面中,我们写的Js是没有读取用户电脑本地文件的权限的,这是出于浏览器运行时的安全考虑的,但在我们在使用h5打包app时,如果再像浏览器上让用户下载,上传文件,就会使用户的使用体验远不如电脑上操作,而且经常会有一些想要缓存本地的数据,cookies太小,满足不了需求,所以就想到能不能有内容时,我能直接操作手机的存取,我使用的是hbuilder打包app的,所以到官网上找找,就找到了有一节专门关于io的介绍,研究了一下使用方法,所以特此记录一下

    本文所参考官方文档 https://www.html5plus.org/doc/zh_cn/io.html 

    先明确几个主要对象及方法,这里与java里的对照来看,会java的朋友可能会更容易理解

    requestFileSystem  请求本地文件系统对象的方法,获取指定的文件系统,可通过type指定获取文件系统的类型。 获取指定的文件系统对象成功通过succesCB回调返回,失败则通过errorCB返回。 

    参数:

      •  type: ( Number ) 必选 本地文件系统常量
      • 可取plus.io下的常量,如plus.io.PRIVATE_DOC、plus.io.PUBLIC_DOCUMENTS等。
      • succesCB: ( FileSystemSuccessCallback ) 必选 请求文件系统成功的回调
      • errorCB: ( FileErrorCallback ) 可选 请求文件系统失败的回调

    注意,这里的type取值共4个,对应于不同的空间,也有不同的访问权限限制,一定要注意区分,如果读取或写入文件时报错时,记得检查这个地方, 以下为原文

    为了安全管理应用的资源目录,规范对文件系统的操作,5+ API在系统应用目录的基础设计了应用沙盒目录, 分为私有目录和公共目录两种类型,私有目录仅应用自身可以访问,公共目录在多应用环境时(如小程序SDK)所有应用都可访问。

    DirectoryEntry 文件系统中的目录对象,用于管理特定的本地目录或者文件,对应于java中可以理解为File对象,这是操作文件最基础的对象,一个directoryEntry对象就对应于一个文件或文件夹

    属性:

      • isFile: 操作对象的是否为文件,DirectoryEntry对象固定其值为false
      • isDirectory: 操作对象是否为目录,DirectoryEntry对象固定其值为true
      • name: 目录操作对象的名称,不包括路径
      • fullPath: 目录操作对象的完整路径,文件系统的绝对路径
      • fileSystem: 文件操作对象所属的文件系统对象,参考FileSystem

    方法:

    FileEntry 文件系统中的文件对象,用于管理特定的本地文件,对应于java中可以理解为File对象

    属性:

      • isFile: 文件操作对象的是否为文件,FileEntry对象固定其值为true
      • isDirectory: 文件操作对象是否为目录,FileEntry对象固定其值为false
      • name: 文件操作对象的名称,不包括路径
      • fullPath: 文件操作对象的完整路径,文件系统的绝对路径
      • fileSystem: 文件操作对象所属的文件系统对象,参考FileSystem

    方法:

      • getMetadata: 获取文件的属性信息
      • moveTo: 移动文件
      • copyTo: 拷贝文件
      • toURL: 获取文件路径转换为URL地址
      • toLocalURL: 获取文件路径转换为本地路径URL地址
      • toRemoteURL: 获取文件路径转换为网络路径URL地址
      • remove: 删除文件
      • getParent: 获取文件所属的父目录
      • createWriter: 获取文件关联的写文件操作对象FileWriter
      • file: 获取文件数据对象

    FileReader 创建读取文件对象,主要是文件读取相关的操作,文件以文本或者Base64编码的字符串形式读出来,对应于java中可理解为InputStream

    属性:

      • readyState: 当前读取文件所处的状态
      • result: 已读取文件的内容
      • error: 文件操作错误代码

    方法:

      • abort: 终止文件读取操作
      • readAsDataURL: 以URL编码格式读取文件数据内容
      • readAsText: 以文本格式读取文件数据内容

    事件:

      • onloadstart: 读取文件开始时的回调函数
      • onload: 读取文件成功完成的回调函数
      • onabort: 取消读取文件时的回调函数
      • onerror: 文件读取操作失败时调用的回调函数
      • onloadend: 文件读取操作完成时的回调函数

    FileWriter 文件系统中的写文件对象,用于写入文件内容,用户注册自己的事件监听器来接收writestart、progress、write、writeend、error和abort事件,一个FileWriter对象是为单个文件的操作而创建,可以使用该对象多次对相应文件进行写入操作。 FileWriter维护该文件的指针位置及长度属性,这样就可以寻找和写入文件的任何地方。 默认情况下,FileWriter从文件的开头开始写入(将覆盖现有数据),seek方法可设置文件操作指定位置,如fw.seek(fw.length-1)写入操作就会从文件的末尾开始 ,对应于java中理解为OutputStream

    属性:

      • readyState: 当前写入文件所处的状态
      • length: 文件当前的长度,单位为字节
      • position: 文件当前操作的指针位置
      • error: 文件写入操作错误代码

    方法:

      • abort: 终止文件写入操作
      • seek: 定位文件操作位置
      • truncate: 按照指定长度截断文件
      • write: 向文件中写入数据

    事件:

      • onwritestart: 写入文件开始时的回调函数
      • onwrite: 写入文件成功完成的回调函数
      • onabort: 取消写入文件时的回调函数
      • onerror: 文件写入操作失败时调用的回调函数
      • onwriteend: 文件写入操作完成时的回调函数

    下面是读写文件的主要代码及说明

    1、获取文件读写的基础,FileEntry对象

     1     //读取应用公共文档目录
     2     plus.io.requestFileSystem(plus.io.PUBLIC_DOCUMENTS, function(fs) {
     3         // 通过fs.root获取DirectoryEntry对象进行操作,获取文件操作的根目录
     4         //这里的filePath即你要读取的文件所在的相对路径,可随意定义,但不得是 _www开头,因为_www开头是应用私有资源目录的专用,只有读权限,不能写入,写入时会报错
     5         var filePath = 'abc/haha/test.txt';
     6         var rootDirectoryEntry = fs.root;
     7         rootDirectoryEntry.getFile(filePath, {
     8             //这个参数的作用是 指示如果文件或目录不存在时是否进行创建,默认值为false,设为true表示如果这个filePath下的test.txt文件不存在就创建,当然,如果存在就直接返回,不会创建
     9             create: true
    10         }, function(fileEntry) {
    11             //FileEntry对象获取成功,对应就是test.txt文件了,可以接着进行相应的读写操作了
    12             
    13         }, function(e) {
    14             console.log(e.message);
    15         });
    16     }, function(e) {
    17         console.log(e.message);
    18     });

    2、在上一步获取到文件操作对象FileEntry的基础上,开始读操作

     1     //获取文件
     2     fileEntry.file(function (file) {
     3         //console.log(file.size + ' <--> ' + file.name);
     4         //创建一个文件读取工具,在java中理解就是InputStream输入流
     5         var fileReader = new plus.io.FileReader();
     6         //成功读取到文件内容时的回调,其中evt.target.result就是文件中的文本内容
     7         fileReader.onloadend = function (evt) {
     8             console.log(evt.target.result);
     9         }
    10         //文件读取操作失败时调用的回调函数
    11         fileReader.onerror = function (e) {
    12             console.log(e.message);
    13         }
    14         //将刚才请求到的文件以utf-8编码,文本的形式读出
    15         fileReader.readAsText(file, 'utf-8');
    16     });

    3、还是以文件操作对象FileEntry为基础,进行写入文件的操作

     1     //通过fileEntry的createWriter创建输出流,向文件写入内容,对应java中的OutputStream
     2     fileEntry.createWriter(writer => {
     3         //文件写入成功后的回调
     4         writer.onwrite = function(event) {
     5             //写入成功
     6             console.log('写入成功');
     7         }
     8         //文件写入操作失败时调用的回调函数
     9         writer.onerror = function(e) {
    10             console.log(e.message);
    11         }
    12         //设置文件写入的起点,writer.length就是上次文件里面内容的最后位置,这样即将新的内容追加到文本最末尾,如果想覆盖原先的内容,直接设置为0即可
    13         var cursor =  writer.length;
    14         writer.seek(cursor);
    15         //将要写入的文本dataStr写入到文件中去
    16         writer.write(dataStr);
    17     }, function(e) {
    18         console.log(e.message);
    19     });

    以上就是在Hbuilder中打包H5的App读写文件的主要代码了及功能了

    但是我们发现这样写会有无数的回调函数,不仅不好看,别人调用时也不好传参,所以我们可以采用ES6的写法加上Primse来封装改造一下,让这些方法看起来更加优雅一点

     1     getFileEntry(filePath) {
     2         return new Promise((resolve, reject) => {
     3             plus.io.requestFileSystem(plus.io.PUBLIC_DOCUMENTS, fs => {
     4                 fs.root.getFile(filePath, {create: true}, fileEntry => {
     5                     resolve(fileEntry);
     6                 }, e => {
     7                     reject(e)
     8                 });
     9             }, e => {
    10                 reject(e)
    11             });
    12         })
    13     },
    14     readData(fileEntry) {
    15         return new Promise((resolve, reject) => {
    16             fileEntry.file(function (file) {
    17                 let fileReader = new plus.io.FileReader();
    18                 fileReader.onloadend = function (evt) {
    19                     resolve(evt.target.result);
    20                 }
    21                 fileReader.onerror = function (e) {
    22                     reject(e)
    23                 }
    24                 fileReader.readAsText(file, 'utf-8');
    25             });
    26         })
    27     },
    28     writeData(fileEntry, dataStr, cursorStart) {
    29         return new Promise((resolve, reject) => {
    30             fileEntry.createWriter(writer => {
    31                 writer.onwrite = e => {
    32                     resolve()
    33                 }
    34                 writer.onerror = e => {
    35                     reject(e)
    36                 }
    37                 //设置文件写入的起点
    38                 let length = cursorStart != undefined ? cursorStart : writer.length;
    39                 writer.seek(length);
    40                 writer.write(dataStr);
    41             }, e => {
    42                 reject(e)
    43             });
    44         })
    45     }

    这样在调用时,代码就会非常简洁了

    读取文件内容

     1     let filePath = '/abc/haha/test.json';
     2     this.getFileEntry(filePath)
     3     .then(fileEntry => {
     4         // fileEntry.remove();    //删除文件
     5         return this.readData(fileEntry);
     6     }).then(fileText => {
     7         alert("文件内容:>>> " + fileText)
     8     }).catch(e => {
     9         alert('文件读取失败!')
    10     })

    写入文件内容

    1     let writeDataStr = 'Hello World!!!'
    2     this.getFileEntry()
    3     .then(fileEntry => {
    4         return this.writeData(fileEntry, writeDataStr);
    5     }).then(writer => {
    6         alert('保存成功');    
    7     }).catch(e => {
    8         alert('保存失败!')
    9     })

    OK ! 打完收工

  • 相关阅读:
    合约广告系统-在线分配问题
    合约广告系统-合约广告系统
    合约广告系统-常用广告系统开源工具
    knnsearch
    ISOMAP和MDS降维
    dijstra算法
    矩阵大于某个数置零
    mathtype 公式分节隐藏
    fifo 实现问题
    vhdl 数据类型转换 使用IEEE标准库numeric_std 需要进行两次转换 use ieee.numeric_std.all;
  • 原文地址:https://www.cnblogs.com/aforever/p/14015401.html
Copyright © 2011-2022 走看看