google-chrome-app - 使用 Chrome FileSystem,让用户选择一个目录,在里面加载文件。并将文件保存在该目录中而无需再次提示

标签 google-chrome-app

我找不到这种情况的任何例子,所以我们开始吧:

我希望用户选择一个目录,加载其中的所有文件,更改它们,然后保存此文件以覆盖它或在同一目录中保存一个新文件,而不询问他要保存的位置。

  • 不知道如何列出目录
  • 的文件
  • 不提示文件选择器窗口
  • 不知道如何将文件保存在目录中

    我相信这是可能的,因为我在这里看到了类似的东西(最后一段):
    http://www.developer.com/lang/using-the-file-api-outside-the-sandbox-in-chrome-packaged-apps.html

    任何答案将不胜感激,谢谢

    编辑:感谢 Chris Johnsen 给了我这个很好的答案:
    var fileHandler = function() {
    
      var _entry = null;
    
      this.open = function(cb) {
    
        chrome.fileSystem.chooseEntry({
          type: 'openDirectory'
        }, function(dirEntry) {
    
          if (!dirEntry || !dirEntry.isDirectory) {
            cb && cb(null);
            return;
          }
    
          _entry = dirEntry;
    
          listDir(_entry, cb);
        });
    
    
      };
    
      this.save = function(filename, source) {
    
        chrome.fileSystem.getWritableEntry(_entry, function(entry) {
    
          entry.getFile(filename, {
            create: true
          }, function(entry) {
            entry.createWriter(function(writer) {
    
              writer.onwrite = function() {
                writer.onwrite = null;
                writer.truncate(writer.position);
              };
    
              writer.write(new Blob([source], {
                type: 'text/javascript'
              }));
            });
          });
    
        });
    
      };
    
      this.saveAs = function(filename, source) {
    
        chrome.fileSystem.chooseEntry({
          type: 'openDirectory'
        }, function(entry) {
    
          chrome.fileSystem.getWritableEntry(entry, function(entry) {
    
            entry.getFile(filename, {
              create: true
            }, function(entry) {
              entry.createWriter(function(writer) {
    
                writer.onwrite = function() {
                  writer.onwrite = null;
                  writer.truncate(writer.position);
                };
    
                writer.write(new Blob([source], {
                  type: 'text/javascript'
                }));
              });
            });
    
          });
        });
    
      };
    
      var listDir = function(dirent, cb, listing) {
          if (listing === undefined) {
            listing = [];
          }
    
          var reader = dirent.createReader();
    
          var read_some = reader.readEntries.bind(reader, function(ents) {
    
            if (ents.length === 0) {
              return cb && cb(listing);
            }
    
            var process_some = function(ents, i) {
    
                for (; i < ents.length; i++) {
                  listing.push(ents[i]);
    
                  if (ents[i].isDirectory) {
                    return listDir(ents[i], process_some.bind(null, ents, i + 1), listing);
                  }
                }
    
                read_some();
              };
    
            process_some(ents, 0);
    
          }, function() {
            console.error('error reading directory');
          });
    
          read_some();
        };
    
    };
    

    最佳答案

    您的 save对于您的第二个要求(写入代码选择的文件名而无需其他用户提示),该方法应该可以正常工作(大部分情况见下文),但 open 中有几个错误(至少如问题中所述):

  • 里面chooseEntry回调,this !== fileHandler因为回调是用不同的 this 调用的(可能是背景页面的 window 对象)。
    您可以通过多种方式解决此问题:
  • 使用fileHandler而不是 this (如果您不将其用作任何类型的原型(prototype))。
  • 使用.bind(this)将每个回调函数绑定(bind)到相同的上下文。
  • 使用var self = this;open 的顶部并使用 self.entry (等等)在回调中。
  • 您可以调用cb为成功案例。也许你有另一种方式来推迟调用(例如)fileHandler.save (单击某个元素以触发保存?),但添加类似
    ⋮
    cb && cb(self.entry);
    ⋮
    

    self.entry = dirEntry 之后使(例如)链接 open 变得容易和 save :
    fileHandler.open(function(ent) {
        fileHandler.save('newfile','This is the text\nto save in the (possibly) new file.');
    });
    

  • save 中存在潜在错误: 如果你覆盖了一个现有的文件,那么你需要调用 writer.truncate() (除非您总是写入比最初保存的文件更多的字节)。
    ⋮
    writer.onwrite = function() {
        writer.onwrite = null;
        writer.truncate(writer.position);
    };
    writer.write(…);
    ⋮
    

    看起来您在文件列表部分有了一个良好的开端。如果您想稍后引用文件列表,那么您可能希望将它们保存在您的对象中,而不是仅仅记录它们;如果您想递归到子目录中,这可能会有点麻烦(并且也不假设 readEntries 第一次调用返回所有内容)。
    function list_dir(dirent, cb, listing) {
        if (listing === undefined) listing = [];
        var reader = dirent.createReader();
        var read_some = reader.readEntries.bind(reader, function(ents) {
            if (ents.length === 0)
                return cb && cb(listing);
            process_some(ents, 0);
            function process_some(ents, i) {
                for(; i < ents.length; i++) {
                    listing.push(ents[i]);
                    if (ents[i].isDirectory)
                        return list_dir(ents[i], process_some.bind(null, ents, i + 1), listing);
                }
                read_some();
            }
        }, function() {
            console.error('error reading directory');
        });
        read_some();
    }
    

    您可以在 open 中使用它回调(假设您添加了它的成功回调),如下所示:
    fileHandler.open(function(ent) {
        ent && list_dir(ent, function(listing) {
            fileHandler.listing = listing;
            console.log('listing', fileHandler.listing.map(function(ent){return ent.fullPath}).join('\n'));
            fileHandler.save('a_dir/somefile','This is some data.');
        });
    });
    

    关于google-chrome-app - 使用 Chrome FileSystem,让用户选择一个目录,在里面加载文件。并将文件保存在该目录中而无需再次提示,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21896363/

    相关文章:

    javascript - Chrome 应用程序 : How to create a hovering circle icon like google hangout app?

    javascript - 在 Chrome 扩展程序下拉列表中显示倒计时

    javascript - 在 chrome 打包应用程序中模仿 cookies 行为

    google-chrome - 从网页激活 Chrome 应用程序?

    google-chrome-app - Chromebox 上的 ChromeOS 中的双屏信息亭模式?

    javascript - 使用 chrome.notifications.create 时出错 "Uncaught TypeError: Cannot read property ' create' of undefined"

    android - 在 PhoneGap/Chrome 应用程序中存储视频以供离线使用

    sockets - 用于身份验证的 chrome 应用程序客户端证书

    javascript - Chrome 应用 : Execute function defined in an app window from a background script

    dart - Google+ api 与 dart chrome 应用程序 - 403 每日限制