DIR : /home/kozerus/public_html/koh5_fileapi.html

/home/kozerus/public_html

<html lang="en" dir="ltr" itemscope itemtype="http://schema.org/Article">
<head>
  <meta charset="utf-8">
  <meta property="twitter:account_id" content="1593210261" />
  <!-- Copyright (c) 2012 Google Inc.
   *
   * Licensed under the Apache License, Version 2.0 (the "License");
   * you may not use this file except in compliance with the License.
   * You may obtain a copy of the License at
   *
   *     http://www.apache.org/licenses/LICENSE-2.0
   *
   * Unless required by applicable law or agreed to in writing, software
   * distributed under the License is distributed on an "AS IS" BASIS,
   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   * See the License for the specific language governing permissions and
   * limitations under the License.
   *
   * Author: Eric Bidelman - e.bidelman@google.com
   *
   * 
   *
  -->
  <title>h5rocks  Exploring the FileSystem APIs - HTML5 Rocks</title>
  <meta name="description" content="The FileSystem APIs give applications the ability to read/write files and directories in a secure, sandboxed file system on a user&#39;s local machine.">
  <meta name="keywords" content="html5,html 5,html5 demos,html5 examples,javascript,css3,notifications,geolocation,web workers,apppcache,file api,filereader,indexeddb,offline,audio,video,drag and drop,chrome,sse,mobile">
  <meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0">
  <meta name="theme-color" content="#f04530">
  <link rel="shortcut icon" href="/favicon.ico">
   <meta itemprop="name" content="Exploring the FileSystem APIs - HTML5 Rocks">
  
  <meta itemprop="image" content="http://www.html5rocks.com/static/images/html5rocks-logo-wings.png">
  

  
  
  <link rel="alternate" hreflang="de" href="loc/de/">
  
  <link rel="alternate" hreflang="es" href="loc/es/">
  
  <link rel="alternate" hreflang="it" href="loc/it/">
  
  <link rel="alternate" hreflang="ja" href="loc/ja/tutorials/file/filesystem/">
  
  <link rel="alternate" hreflang="ko" href="loc/ki/tutorials/file/filesystem/">
  
  <link rel="alternate" hreflang="ru" href="loc/ru/tutorials/file/filesystem/">
  
  <link rel="alternate" hreflang="zh" href="loc/zh/tutorials/file/filesystem/">
  
  

  
    
    <link rel="stylesheet" media="all" href="lib/css/v2-combined.min_20131111.css">
    

    
  

  <link href="//fonts.googleapis.com/css?family=Open+Sans:300,400,400italic,600,800|Source+Code+Pro" rel="stylesheet">

  <link rel="apple-touch-icon" href="/static/images/identity/HTML5_Badge_64.png">
  <link rel="apple-touch-icon-precomposed" href="/static/images/identity/HTML5_Badge_64.png">

  <script src="lib/js/modernizr.custom.82437.js"></script>

	<!--[if lt IE 9]>
		<script src="http://html5shim.googlecode.com/svn/trunk/html5-els.js"></script>
		<![endif]-->

  
	<style>

		</style>

	</head>




<body data-href="tutorials-file-filesystem" onload="" class="article tutorial">

  <header class="main" id="siteheader">
    <h1 id="title">
      <a href="/en/" title="koh5rocks">koh5rocks</a>
    </h1>
    <a href="#sitenav" id="navtoggle">Show navigation</a>

    
    <a id="toctoggle" href="#toc">toc</a>
    

    <nav id="sitenav">
      <ul>
        
        <li id="home_menu"><a href="/en/" class="home">Home</a></li>
        
        <li id="tutorials_menu"><a href="/en/tutorials/?page=1" class="tutorials">Tutorials</a></li>
        <li id="updates_menu"><a href="http://updates.html5rocks.com/" class="updates">Updates</a></li>
      </ul>
    </nav>

    
	<nav class="toc" id="toc">
		<h1>Table of Contents</h1>

		<ul>
			<li><a href='#toc-introduction'>Introduction</a></li>
			<li><a href='#toc-requesting'>Requesting a file system</a></li>
			<li><a href='#toc-file'>Working with files</a></li>
			<li><a href='#toc-dir'>Working with directories</a></li>
			<li><a href='#toc-copy-rename-move'>Copying, renaming, and moving</a></li>
			<li><a href='#toc-filesystemurls'>filesystem: URLs</a></li>
			<li><a href='#toc-dir-fullexample'>Putting it all together</a></li>
			<li><a href='#toc-usecases'>Use Cases</a></li><li><a href='#toc-references'>Reference specifications</a></li>
				</ul>

		<h1 class="visible-title">Localizations:</h1>
		<ul>
			<li><a href="/de/tutorials/file/filesystem/">Deutsch</a></li>
          
			<li><a href="/it/tutorials/file/filesystem/">Italiano</a></li>
          
			<li><a href="/ja/tutorials/file/filesystem/">???</a></li>
          
          
			<li><a href="/ru/tutorials/file/filesystem/">P??????</a></li>
          
			<li><a href="/zh/tutorials/file/filesystem/">?? (??)</a></li>
			</ul>
		</nav>
    
		</header>

		<div class="body-content">
 		<section class="title">
			<section class="title-text container">
      
				<h1>ka6/ko/index.html</h1>
				<a href="/en/" class="watermark">HTML5 Rocks</a>
				</section>
 			 </section>

		<article class="content-wrapper">

			<section class="container">

      

				<div class="article-meta" id="article-meta">
					<nav class="toc">
						<h1>toc</h1>

						<ul>
<li><a href='#toc-introduction'>Introduction</a></li>
<li><a href='#toc-requesting'>Requesting a file system</a></li>
<li><a href='#toc-file'>Working with files</a></li>
<li><a href='#toc-dir'>Working with directories</a></li>
<li><a href='#toc-copy-rename-move'>Copying, renaming, and moving</a></li>
<li><a href='#toc-filesystemurls'>filesystem: URLs</a></li>
<li><a href='#toc-dir-fullexample'>Putting it all together</a></li>
<li><a href='#toc-usecases'>Use Cases</a></li>
<li><a href='#toc-references'>Reference specifications</a></li>
								</ul>
					</nav>

		<aside class="localizations">
			<h1>Loc</h1>
				<ul>
            
              
              <li><a href="/de/tutorials/file/filesystem/">Deutsch</a></li>
              
              
              <li><a href="/it/tutorials/file/filesystem/">Italiano</a></li>
              
              <li><a href="/ja/tutorials/file/filesystem/">???</a></li>
              
              
              <li><a href="/ru/tutorials/file/filesystem/">P??????</a></li>
              
              <li><a href="/zh/tutorials/file/filesystem/">?? (??)</a></li>
              
              <li><a href="https://github.com/html5rocks/www.html5rocks.com/blob/master/CONTRIBUTING.md">Contribute another</a></li>
            
			</ul>
		</aside>
	</div>
      

      <div class="content" id="article-content">

        <section class="byline">

          <div class="byline-content">
            
            <section class="author-images">
              <a href="/profiles/#ericbidelman">
                <img src="/static/images/profiles/ericbidelman.png" itemprop="photo" alt="Eric Bidelman" title="Eric Bidelman">
              </a>

              
            </section>

            <section class="meta">
              <div class="authors">
                <strong>By</strong> <a href="/profiles/#ericbidelman">Eric Bidelman</a>
                
              </div>

              

              <div class="date">
                <time pubdate><strong>Published:</strong> January 4th, 2011</time>
                
                <time class="updated"><strong>Updated:</strong> July 30th, 2013</time>
                <span><strong>Comments:</strong> <a href="#disqus_thread" class="load-comments" data-disqus-identifier="http://www.html5rocks.com/tutorials/file/filesystem/">0</a></span>
              </div>

              <div id="notcompatible" class="hidden">
                Your browser may not support the functionality in this article.
              </div>
            </section>
            <div class="clear"></div>

            
          </div>
        </section>

        
   <p>The API is broken up into various themes:</p>
  <ul>
    <li>Reading and manipulating files:
      <code>File</code>/<code>Blob</code>, <code>FileList</code>, <code>FileReader</code></li>
    <li>Creating and writing:
      <code>Blob()</code>, <code>FileWriter</code></li>
    <li>Directories and file system access:
      <code>DirectoryReader</code>, <code>FileEntry</code>/<code>DirectoryEntry</code>, <code>LocalFileSystem</code>
    </li>
  </ul>

  <h3 id="toc-support">Browser support &amp; storage limitations</h3>

  <h2 id="toc-requesting">Requesting a file system</h2>
	<pre class="prettyprint">
// Note: The file system has been prefixed as of Google Chrome 12:
		window.requestFileSystem  = window.requestFileSystem || window.webkitRequestFileSystem;

		window.requestFileSystem(<var>type</var>, <var>size</var>, <var>successCallback</var>, <var>opt_errorCallback</var>)
		</pre>

	<p>Example usage:</p>
	<pre class="prettyprint">
		function onInitFs(fs) {
			console.log('Opened file system: ' + fs.name);
			}

		<b>window.requestFileSystem</b>(<b>window.TEMPORARY</b>, 5*1024*1024 /*5MB*/, onInitFs, errorHandler);
		</pre>
	
	<pre class="prettyprint">
		function errorHandler(e) {
			var msg = '';

			switch (e.code) {
				case <b>FileError.QUOTA_EXCEEDED_ERR</b>:
					msg = 'QUOTA_EXCEEDED_ERR';
					break;
				case <b>FileError.NOT_FOUND_ERR</b>:
					msg = 'NOT_FOUND_ERR';
					break;
				case <b>FileError.SECURITY_ERR</b>:
					msg = 'SECURITY_ERR';
					break;
				case <b>FileError.INVALID_MODIFICATION_ERR</b>:
					msg = 'INVALID_MODIFICATION_ERR';
					break;
				case <b>FileError.INVALID_STATE_ERR</b>:
					msg = 'INVALID_STATE_ERR';
					break;
				default:
					msg = 'Unknown Error';
					break;
				};

			console.log('Error: ' + msg);
			}
		</pre>

	<pre class="prettyprint">
		window.webkitStorageInfo.requestQuota(PERSISTENT, 1024*1024, function(grantedBytes) {
		window.requestFileSystem(PERSISTENT, grantedBytes, onInitFs, errorHandler);
		}, function(e) {
			console.log('Error', e);
			});
		</pre>


	<p id="toc-fileentry">Properties and methods of <code>FileEntry</code>:</p>
	<pre class="prettyprint">
		fileEntry.isFile === true
		fileEntry.isDirectory === false
		fileEntry.name
		fileEntry.fullPath
		...

		fileEntry.getMetadata(successCallback, opt_errorCallback);
		fileEntry.remove(successCallback, opt_errorCallback);
		fileEntry.moveTo(dirEntry, opt_newName, opt_successCallback, opt_errorCallback);
		fileEntry.copyTo(dirEntry, opt_newName, opt_successCallback, opt_errorCallback);
		fileEntry.getParent(successCallback, opt_errorCallback);
		fileEntry.toURL(opt_mimeType);
	
		fileEntry.file(successCallback, opt_errorCallback);
		fileEntry.createWriter(successCallback, opt_errorCallback);
		...
		</pre>

	<p>The following code creates an empty file called "log.txt" in the root of the app's file system:</p>

	<pre class="prettyprint">
		function onInitFs(fs) {

			<b>fs.root.getFile</b>('log.txt', <b>{create: true, exclusive: true}</b>, function(fileEntry) {
	
// fileEntry.name == 'log.txt'
// fileEntry.fullPath == '/log.txt'

			}, errorHandler);

		}

		window.requestFileSystem(window.TEMPORARY, 1024*1024, onInitFs, errorHandler);
		</pre>

 
	<h3 id="toc-file-readingbyname">Reading a file by name</h3>
	<pre class="prettyprint">
		function onInitFs(fs) {

		<b>fs.root.getFile</b>('log.txt', {}, function(fileEntry) {

// Get a File object representing the file,
// then use FileReader to read its contents.
			fileEntry.<b>file</b>(function(file) {
				var reader = new FileReader();

				reader.onloadend = function(e) {
				var txtArea = document.createElement('textarea');
				txtArea.value = this.result;
				document.body.appendChild(txtArea);
				};

			reader.readAsText(file);
			}, errorHandler);

			}, errorHandler);

		}

	window.requestFileSystem(window.TEMPORARY, 1024*1024, onInitFs, errorHandler);
	</pre>

	<h3 id="toc-file-writing">Writing to a file</h3>

	<p>The following code creates an empty file called "log.txt" (if it doesn't exist)
		and fills it with the text 'Lorem Ipsum'.</p>

	<pre class="prettyprint">
		function onInitFs(fs) {

			<b>fs.root.getFile</b>('log.txt', <b>{create: true}</b>, function(fileEntry) {

// Create a FileWriter object for our FileEntry (log.txt).
			<b>fileEntry.createWriter</b>(function(fileWriter) {

			<b>fileWriter.onwriteend</b> = function(e) {
				console.log('Write completed.');
				};

			<b>fileWriter.onerror</b> = function(e) {
				console.log('Write failed: ' + e.toString());
				};

// Create a new Blob and write it to log.txt.
		var blob = new Blob(['Lorem Ipsum'], {type: 'text/plain'});

		<b>fileWriter.write</b>(blob);

			}, errorHandler);

			}, errorHandler);

		}

		window.requestFileSystem(window.TEMPORARY, 1024*1024, onInitFs, errorHandler);
		</pre>

  <p>This time, we call the FileEntry's <code>createWriter()</code> method to
  obtain a <code>FileWriter</code> object. Inside the success callback, event
  handlers are set up for <code>error</code> and <code>writeend</code> events.
  The text data is written to the file by creating a blob, appending text to it,
  and passing the blob to <code>FileWriter.write()</code>.</p>

  <h3 id="toc-file-appending">Appending data to a file</h3>

  <p>The following code appends the text 'Hello World' to the end of our log file.
  An error is thrown if the file does not exist.</p>

  <pre class="prettyprint">
function onInitFs(fs) {

  <b>fs.root.getFile</b>('log.txt', <b>{create: false}</b>, function(fileEntry) {

    // Create a FileWriter object for our FileEntry (log.txt).
    fileEntry.createWriter(function(fileWriter) {

      <b>fileWriter.seek(fileWriter.length); // Start write position at EOF.</b>

      // Create a new Blob and write it to log.txt.
      var blob = new Blob(['Hello World'], {type: 'text/plain'});

      <b>fileWriter.write</b>(blob);

    }, errorHandler);

  }, errorHandler);

}

window.requestFileSystem(window.TEMPORARY, 1024*1024, onInitFs, errorHandler);
</pre>

  <h3 id="toc-file-user-selected">Duplicating user-selected files</h3>

  <p>The following code allows a user to select multiple files using
  <code>&lt;input type="file" multiple /&gt;</code> and creates copies of those
  files in the app's sandboxed file system.</p>

  <pre class="prettyprint">&lt;input type="file" id="myfile" <b>multiple</b> /&gt;</pre>

  <pre class="prettyprint">
document.querySelector('#myfile').onchange = function(e) {
  var files = <b>this.files</b>;

  window.requestFileSystem(window.TEMPORARY, 1024*1024, function(fs) {
    // Duplicate each file the user selected to the app's fs.
    for (var i = 0, file; file = files[i]; ++i) {

      // Capture current iteration's file in local scope for the getFile() callback.
      (function(f) {
        fs.root.getFile(<b>f.name</b>, {create: true, exclusive: true}, function(fileEntry) {
          fileEntry.createWriter(function(fileWriter) {
            <b>fileWriter.write(f);</b> // Note: write() can take a File or Blob object.
          }, errorHandler);
        }, errorHandler);
      })(file);

    }
  }, errorHandler);

};
</pre>

  <p>Although we've used an input for the file import, one could easily leverage
  <a href="/tutorials/dnd/basics/#toc-desktop-dnd-into">HTML5 Drag and Drop</a>
  to achieve the same objective.</p>

  <p>As noted in the comment, <code>FileWriter.write()</code> can accept a <code>Blob</code>
  or <code>File</code>. This is because <code>File</code> inherits from <code>Blob</code>.
  Therefore, all file objects are blobs.</p>

  <h3 id="toc-file-removing">Removing a file</h3>

  <p>The following code deletes the file 'log.txt'.</p>

  <pre class="prettyprint">
window.requestFileSystem(window.TEMPORARY, 1024*1024, function(fs) {
  fs.root.getFile('log.txt', {create: false}, function(fileEntry) {

    <b>fileEntry.remove(function() {
      console.log('File removed.');
    }, errorHandler);</b>

  }, errorHandler);
}, errorHandler);
</pre>

  <h2 id="toc-dir">Working with directories</h2>

  <p>Directories in the sandbox are represented by the
  <a href="http://dev.w3.org/2009/dap/file-system/pub/FileSystem/#the-directoryentry-interface"><code>DirectoryEntry</code></a>
  interface, which shares most of <a href="#toc-fileentry">FileEntry</a>'s properties
  (they inherit from a common <code>Entry</code> interface). However, <code>DirectoryEntry</code>
  has additional methods for manipulating directories.</p>

  <p>Properties and methods of <code>DirectoryEntry</code>:</p>
  <pre class="prettyprint">
dirEntry.isDirectory === true
// See the section on <a href="#toc-fileentry">FileEntry</a> for other inherited properties/methods.
...

var dirReader = dirEntry.createReader();
dirEntry.getFile(path, opt_flags, opt_successCallback, opt_errorCallback);
dirEntry.getDirectory(path, opt_flags, opt_successCallback, opt_errorCallback);
dirEntry.removeRecursively(successCallback, opt_errorCallback);
...
</pre>

  <h3 id="toc-dir-creating">Creating directories</h3>

  <p>Use the <code>getDirectory()</code> method of <code>DirectoryEntry</code>
  to read or create directories. You can pass either a name or path as
  the directory to look up or create.</p>

  <p>For example, the following code creates a directory named "MyPictures" in the
  root directory:</p>

  <pre class="prettyprint">
window.requestFileSystem(window.TEMPORARY, 1024*1024, function(fs) {
  fs.root.<b>getDirectory</b>('MyPictures', {create: true}, function(dirEntry) {
    ...
  }, errorHandler);
}, errorHandler);
  </pre>

  <h3 id="toc-dir-subirs">Subdirectories</h3>

  <p>Creating a subdirectory is exactly the same as creating any other directory. However,
  the API throws an error if you attempt to create a directory whose immediate
  parent does not exist. The solution is to create each directory sequentially, which
  is rather tricky to do with an asynchronous API.</p>

  <p>The following code creates a new hierarchy (music/genres/jazz) in the
  root of the app's FileSystem by recursively adding each subdirectory after its
  parent folder has been created.</p>

  <pre class="prettyprint">
var path = 'music/genres/jazz/';

function createDir(rootDirEntry, folders) {
  // Throw out './' or '/' and move on to prevent something like '/foo/.//bar'.
  if (folders[0] == '.' || folders[0] == '') {
    folders = folders.slice(1);
  }
  rootDirEntry.<b>getDirectory</b>(folders[0], <b>{create: true}</b>, function(dirEntry) {
    // Recursively add the new subfolder (if we still have another to create).
    if (folders.length) {
      createDir(dirEntry, folders.slice(1));
    }
  }, errorHandler);
};

function onInitFs(fs) {
  createDir(fs.root, path.split('/')); // fs.root is a DirectoryEntry.
}

window.requestFileSystem(window.TEMPORARY, 1024*1024, onInitFs, errorHandler);
</pre>

  <p>Now that "music/genres/jazz" is in place, we can pass its full path
  to <code>getDirectory()</code> and create new subfolders or files under it.
  For example:</p>

  <pre class="prettyprint">
window.requestFileSystem(window.TEMPORARY, 1024*1024, function(fs) {
  fs.root.getFile('/music/genres/jazz/song.mp3', {create: true}, function(fileEntry) {
    ...
  }, errorHandler);
}, errorHandler);
</pre>

  <h3 id="toc-dir-reading">Reading a directory's contents</h3>

  <p>To read the contents of a directory, create a <code>DirectoryReader</code>
  and call its <code>readEntries()</code> method. There is no
  guarantee that all of a directory's entries will be returned
  in a single call to <code>readEntries()</code>. That means you need to keep calling
  <code>DirectoryReader.readEntries()</code> until no more results are returned.
  The following is code that demonstrates this:</p>

  <pre class="prettyprint">&lt;ul id="filelist"&gt;&lt;/ul&gt;</pre>

  <pre class="prettyprint">
function toArray(list) {
  return Array.prototype.slice.call(list || [], 0);
}

function listResults(entries) {
  // Document fragments can improve performance since they're only appended
  // to the DOM once. Only one browser reflow occurs.
  var fragment = document.createDocumentFragment();

  entries.forEach(function(entry, i) {
    var img = <b>entry.isDirectory</b> ? '&lt;img src="folder-icon.gif"&gt;' :
                                  '&lt;img src="file-icon.gif"&gt;';
    var li = document.createElement('li');
    li.innerHTML = [img, '&lt;span&gt;', entry.name, '&lt;/span&gt;'].join('');
    fragment.appendChild(li);
  });

  document.querySelector('#filelist').appendChild(fragment);
}

function onInitFs(fs) {

  var dirReader = <b>fs.root.createReader()</b>;
  var entries = [];

  // Call the reader.readEntries() until no more results are returned.
  var readEntries = function() {
     <b>dirReader.readEntries </b>(function(results) {
      if (!results.length) {
        listResults(entries.sort());
      } else {
        entries = entries.concat(toArray(results));
        readEntries();
      }
    }, errorHandler);
  };

  readEntries(); // Start reading dirs.

}

window.requestFileSystem(window.TEMPORARY, 1024*1024, onInitFs, errorHandler);
</pre>

  <h3 id="toc-dir-removing">Removing a directory</h3>

  <p>The <code>DirectoryEntry.remove()</code> method behaves just like
  <a href="#toc-file-removing"><code>FileEntry</code></a>'s. The difference:
  attempting to delete a non-empty directory results in an error.</p>

  <p>The following removes the empty directory "jazz" from "/music/genres/":</p>

  <pre class="prettyprint">
window.requestFileSystem(window.TEMPORARY, 1024*1024, function(fs) {
  fs.root.getDirectory('music/genres/jazz', {}, function(dirEntry) {

    <b>dirEntry.remove(function() {
      console.log('Directory removed.');
    }, errorHandler);</b>

  }, errorHandler);
}, errorHandler);
</pre>

  <h4 id="toc-dir-rremoving">Recursively removing a directory</h4>

  <p>If you have a pesky directory that contains entries, <code>removeRecursively()</code>
  is your friend. It deletes the directory and its contents, recursively.</p>

  <p>The following code recursively removes the directory "music" and all the
  files and directories that it contains:</p>

  <pre class="prettyprint">
window.requestFileSystem(window.TEMPORARY, 1024*1024, function(fs) {
  fs.root.getDirectory('/misc/../music', {}, function(dirEntry) {

    <b>dirEntry.removeRecursively(function() {
      console.log('Directory removed.');
    }, errorHandler);</b>

  }, errorHandler);
}, errorHandler);
</pre>

  <h2 id="toc-copy-rename-move">Copying, renaming, and moving</h2>

  <p><code>FileEntry</code> and <code>DirectoryEntry</code> share common operations.</p>

  <h3 id="toc-dir-move-copy">Copying an entry</h3>

  <p>Both <code>FileEntry</code> and <code>DirectoryEntry</code> have a
  <code>copyTo()</code> for duplicating existing entries. This method automatically
  does a recursive copy on folders.</p>

  <p>The following code example copies the file "me.png" from one directory to another:</p>

  <pre class="prettyprint">
function copy(cwd, src, dest) {
  cwd.getFile(src, {}, function(fileEntry) {

    cwd.getDirectory(dest, {}, function(dirEntry) {
      <b>fileEntry.copyTo</b>(dirEntry);
    }, errorHandler);

  }, errorHandler);
}

window.requestFileSystem(window.TEMPORARY, 1024*1024, function(fs) {
  copy(fs.root, '/folder1/me.png', 'folder2/mypics/');
}, errorHandler);
</pre>

  <h3 id="toc-dir-move-rename">Moving or renaming an entry</h3>

  <p>The <code>moveTo()</code> method present in
  <code>FileEntry</code> and <code>DirectoryEntry</code>
  allows you to move or rename a file or directory.
  Its first argument is the parent directory to move the file under, and its second
  is an optional new name for the file. If a new name isn't provided, the file's
  original name is used.</p>

  <p>The following example renames "me.png" to "you.png", but does not move the file:</p>

  <pre class="prettyprint">
function rename(cwd, src, newName) {
  cwd.getFile(src, {}, function(fileEntry) {
    <b>fileEntry.moveTo</b>(cwd, newName);
  }, errorHandler);
}

window.requestFileSystem(window.TEMPORARY, 1024*1024, function(fs) {
  rename(fs.root, 'me.png', 'you.png');
}, errorHandler);
</pre>

  <p>The following example moves "me.png" (located in the root directory) to
  a folder named "newfolder".</p>

  <pre class="prettyprint">
function move(src, dirName) {
  fs.root.getFile(src, {}, function(fileEntry) {

    fs.root.getDirectory(dirName, {}, function(dirEntry) {
      <b>fileEntry.moveTo</b>(dirEntry);
    }, errorHandler);

  }, errorHandler);
}

window.requestFileSystem(window.TEMPORARY, 1024*1024, function(fs) {
  move('/me.png', 'newfolder/');
}, errorHandler);
</pre>

  <h2 id="toc-filesystemurls">filesystem: URLs</h2>

  <p>The FileSystem API exposes a new URL scheme, <code>filesystem:</code>,
  that can be used to fill <code>src</code> or <code>href</code> attributes.
  For example, if you wanted to display an image and have its
  <a href="http://dev.w3.org/2009/dap/file-system/pub/FileSystem/#the-fileentry-interface"><code>fileEntry</code></a>,
  calling <code>toURL()</code> would give you the file's <code>filesystem:</code> URL:</p>

<pre class="prettyprint">
var img = document.createElement('img');
img.src = <b>fileEntry.toURL</b>(); // filesystem:http://example.com/temporary/myfile.png
document.body.appendChild(img);
</pre>

  <p>Alternatively, if you already have a <code>filesystem:</code> URL,
  <code>resolveLocalFileSystemURL()</code> will get you back the
  <a href="http://dev.w3.org/2009/dap/file-system/pub/FileSystem/#the-fileentry-interface"><code>fileEntry</code></a>:</p>

<pre class="prettyprint">
window.resolveLocalFileSystemURL = window.resolveLocalFileSystemURL ||
                                   window.webkitResolveLocalFileSystemURL;

var url = 'filesystem:http://example.com/temporary/myfile.png';
<b>window.resolveLocalFileSystemURL</b>(url, function(fileEntry) {
  ...
});
</pre>

  <h2 id="toc-dir-fullexample">Putting it all together</h2>

  <h3 id="toc-samples-basic">Basic example</h3>
  <p>This demo lists the files/folders in the filesystem.</p>

  
  <iframe src="http://playground.html5rocks.com/?mode=frame&hu=180&hl=160#filesystem_apis" style="border: none; width: 100%; height: 460px;"></iframe>
  

  <h3 id="toc-samples-terminal">HTML5 Terminal</h3>
  <p>This shell replicates some of the common operations in a UNIX filesystem
  (such as <code>cd</code>, <code>mkdir</code>, <code>rm</code>, <code>open</code>,
  and <code>cat</code>) by abstracting the FileSystem API. To add content, open
  the app, then drag and drop files from your desktop onto the terminal window.</p>

  <!--<iframe id="terminal-iframe" src="terminal.html"></iframe>-->

  <figure>
    <a href="http://www.htmlfivewow.com/demos/terminal/terminal.html"target="_blank">
      <img src="terminal.png" alt="Click to open the HTML5 Wow Terminal" title="Click to open the HTML5 Wow Terminal">
    </a>
    <figcaption>
      <a href="http://www.htmlfivewow.com/demos/terminal/terminal.html"target="_blank">Open the HTML5 Terminal</a>
    </figcaption>
  </figure>

  <h2 id="toc-usecases">Use Cases</h2>

  <p>There are several <a href="/tutorials#offline,storage">storage options</a>
  available in HTML5, but the FileSystem is different in that it aims to satisfy
  client-side storage use cases not well served by databases. Generally, these
  are applications that deal with large binary blobs and/or share data with
  applications outside of the context of the browser.</p>

  <p>The specification lists several use cases:</p>
  <ol>
    <li>Persistent uploader
      <ul>
      <li>When a file or directory is selected for upload, it copies the files
      into a local sandbox and uploads a chunk at a time.</li>
      <li>Uploads can be restarted after browser crashes, network interruptions, etc.</li>
      </ul>
    </li>
    <li>Video game, music, or other app with lots of media assets
      <ul>
      <li>It downloads one or several large tarballs, and expands them locally
      into a directory structure.</li>
      <li>The same download works on any operating system.</li>
      <li>It can manage prefetching just the next-to-be-needed assets in
      the background, so going to the next game level or activating a new
      feature doesn't require waiting for a download.</li>
      <li>It uses those assets directly from its local cache, by direct
      file reads or by handing local URIs to image or video tags, WebGL asset loaders, etc.</li>
      <li>The files may be of arbitrary binary format.</li>
      <li>On the server side, a compressed tarball will often be much
      smaller than a collection of separately-compressed files. Also, 1
      tarball instead of 1000 little files will involve fewer seeks, all
      else being equal.</li>
      </ul>
    </li>
    <li>Audio/Photo editor with offline access or local cache for speed
      <ul>
      <li>The data blobs are potentially quite large, and are read-write.</li>
      <li>It may want to do partial writes to files (ovewriting just the
      ID3/EXIF tags, for example).</li>
      <li>The ability to organize project files by creating directories would be useful.</li>
      <li>Edited files should be accessable by client-side applications [iTunes, Picasa].
      </li></ul>
    </li>
    <li>Offline video viewer
      <ul>
      <li>It downloads large files (&gt;1GB) for later viewing.</li>
      <li>It needs efficient seek + streaming.</li>
      <li>It must be able to hand a URI to the video tag.</li>
      <li>It should enable access to partly-downloaded files e.g. to let
      you watch the first episode of the DVD even if your download didn't
      complete before you got on the plane.</li>
      <li>It should be able to pull a single episode out of the middle of
      a download and give just that to the video tag.</li>
      </ul>
    </li>
    <li>Offline Web Mail Client
      <ul>
      <li>Downloads attachments and stores them locally.</li>
      <li>Caches user-selected attachments for later upload.</li>
      <li>Needs to be able to refer to cached attachments and image
      thumbnails for display and upload.</li>
      <li>Should be able to trigger the UA's download manager just as if
      talking to a server.</li>
      <li>Should be able to upload an email with attachments as a
      multipart post, rather than sending a file at a time in an XHR.</li>
      </ul>
    </li>
  </ol>

  <h2 id="toc-references">Reference specifications</h2>
  <ul>
    <li><a href="http://dev.w3.org/2009/dap/file-system/pub/FileSystem/">FileSystem</a></li>
    <li><a href="http://dev.w3.org/2009/dap/file-system/file-writer.html">FileWriter</a></li>
    <li><a href="http://dev.w3.org/2006/webapi/FileAPI/#dfn-filereader">FileReader</a></li>
    <li><a href="http://dev.w3.org/2006/webapi/FileAPI/">File</a></li>
    <li><a href="http://dev.w3.org/2006/webapi/FileAPI/#dfn-Blob">Blob</a></li>
  </ul>




      </div>
    </section>
  </article>

  
  <section class="disqus pattern-bg-lighter">

    <div id="disqus" class="container">

      <h2>Comments</h2>

      <div id="disqus_thread">

        <a href="#disqus_thread" class="load-comments" data-disqus-identifier="http://www.html5rocks.com/tutorials/file/filesystem/">0</a>

      </div>
    </div>

    <noscript>
      <p class="center">
        <strong>
          <a href="http://disqus.com/?ref_noscript">Please enable JavaScript to view the comments powered by Disqus.</a>
        </strong>
      </p>
    </noscript>

    <script>

      var disqus_shortname = 'html5rocks';
      var disqus_identifier = 'http://www.html5rocks.com/tutorials/file/filesystem/';
      var disqus_url = 'http://www.html5rocks.com/tutorials/file/filesystem/';
      var disqus_developer = 0;

      var disqus_config = function () {
        var funky_language_code_mapping = {
          'de': 'de_inf',
          'es': 'es_ES',
          'pt': 'pt_EU',
          'sr': 'sr_CYRL',
          'sv': 'sv_SE',
          'zh': 'zh_HANT'
        };
        this.language = funky_language_code_mapping['en'] ||
                        'en';

        this.callbacks.onReady = [ function () {
                                      try {
                                        ga('send', 'event', 'View comments');
                                      } catch(err){}
                                   } ];
        this.callbacks.onNewComment = [ function (comment) {
                                          try {
                                            ga('send', 'event', 'Commented');
                                          } catch(err){}
                                        } ];
      };

      window.addEventListener('load', function(e) {

        var c = document.createElement('script');
        c.type = 'text/javascript';
        c.src = 'http://' + disqus_shortname + '.disqus.com/count.js';
        c.async = true;

        var s = document.getElementsByTagName('script')[0], sp = s.parentNode;
        sp.insertBefore(c, s);

        if (window.location.hash === '#disqus_thread')
          loadComments();

      }, false);

      var disqus_loaded = false;
      function loadComments() {

        if (disqus_loaded)
          return;

        disqus_loaded = true;

        ga('send', 'event', 'Interactions', 'Comments', 'Comments Loaded');

        var s = document.getElementsByTagName('script')[0], sp = s.parentNode;
        var dsq = document.createElement('script');
        dsq.type = 'text/javascript';
        dsq.async = true;

        var disqusContainer = document.getElementById('disqus');
        disqusContainer.classList.add('active');

        dsq.src = 'http://' + disqus_shortname + '.disqus.com/embed.js';
        sp.insertBefore(dsq, s);
      }

      function outgoing(url) {
        try {
          ga('send', 'event', 'Outbound Links' , url);
        } catch(err){}
      }
      // Open external links (also that don't have a target defined) in a new tab.
      var externLinks = document.querySelectorAll('article.tutorial a[href^="http"]:not([target])');
      for(var i = 0, a; a = externLinks[i]; ++i) {
        a.target = '_blank';
        a.addEventListener('click', new Function('outgoing(' + '"' + a.href.replace(/.*?:\/\//g, "") + '"' + ');'));
      }

      var loadCommentsButtons = document.querySelectorAll('.load-comments');
      for(var l = 0; l < loadCommentsButtons.length; l++)
        loadCommentsButtons[l].addEventListener('click', loadComments);

    </script>
  </section>
  

  <footer>
    <div class="container">

      
        <h1>Next steps</h2>

        

        <aside class="panel share">
          <h2>Share</h2>

            <a href="https://twitter.com/share?url=http://www.html5rocks.com/tutorials/file/filesystem/&text=Exploring the FileSystem APIs&lang=en&via=ChromiumDev&related=ChromiumDev" class="twitter" target="_blank">Twitter</a>

            <a href="https://www.facebook.com/sharer/sharer.php?u=http://www.html5rocks.com/tutorials/file/filesystem/" class="facebook" target="_blank">Facebook</a>

            <a href="https://plus.google.com/share?url=http://www.html5rocks.com/tutorials/file/filesystem/" class="gplus" onclick="javascript:window.open(this.href, '', 'menubar=no,toolbar=no,resizable=yes,scrollbars=yes,height=600,width=600');return false;">Google+</a>

        </aside>

        <aside class="panel rss">
          <h2>Subscribe</h2>
          <p>Enjoyed this article? Grab the <a href="http://feeds.feedburner.com/html5rocks">RSS feed</a> and stay up-to-date.</p>
        </aside>

      

      <p class="licensing">
      
        Except as otherwise <a href="http://code.google.com/policies.html#restrictions">noted</a>, the content of this page is licensed under the <a href="http://creativecommons.org/licenses/by/3.0/">Creative Commons Attribution 3.0 License</a>, and code samples are licensed under the <a href="http://www.apache.org/licenses/LICENSE-2.0">Apache 2.0 License</a>.
      
      </p>

    </div>
  </footer>

  <script>
    window.isCompatible = function() {
      
  return !!(window.requestFileSystem || window.webkitRequestFileSystem);

    };

    if (isCompatible() === false) {
      document.getElementById('notcompatible').className = '';
    }

    function _prettyPrint() {
      if (typeof customPrettyPrintLanguage != 'undefined') {
        customPrettyPrintLanguage();
      }
      prettyPrint();
    }
  </script>
  <script async src="/static/js/prettify.min.js" onload="_prettyPrint()"></script>
  <!-- Google Tag Manager -->
<noscript><iframe src="//www.googletagmanager.com/ns.html?id=GTM-XXXX"
height="0" width="0" style="display:none;visibility:hidden"></iframe></noscript>
<script>(function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start':
new Date().getTime(),event:'gtm.js'});var f=d.getElementsByTagName(s)[0],
j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src=
'//www.googletagmanager.com/gtm.js?id='+i+dl;f.parentNode.insertBefore(j,f);
})(window,document,'script','dataLayer','GTM-MB3LRF');</script>
<!-- End Google Tag Manager -->


  </div>

  <script>
  (function() {

    // Kill feedburner and marketing tracking arguments, but let them register
    // before we do it.
    setTimeout(function() {
      if (/^\?utm_/.test(document.location.search) &&
          window.history.replaceState) {
        window.history.replaceState(
            {}, '', document.location.href.replace(/\?utm_.*/, ''));
      }
    }, 2000);

    var siteHeader = document.getElementById('siteheader');
    var navToggle = document.getElementById('navtoggle');
    var siteNav = document.getElementById('sitenav');

    function toggle(target, forceActive) {

      if (typeof toc !== 'undefined') {
        // Switch off whichever one is not the
        // current target
        if (target === toc)
          siteNav.classList.remove('active');
        else
          toc.classList.remove('active');
      }

      // Toggle if no force parameter is set
      if (typeof forceActive === 'undefined') {
        target.classList.toggle('active');
      } else {
        if (forceActive)
          target.classList.add('active');
        else
          target.classList.remove('active');
      }

      // now find out what the set state ended up being
      var isActive = target.classList.contains('active');

      if (isActive)
        siteHeader.classList.add('expanded');
      else
        siteHeader.classList.remove('expanded');

    }

    navToggle.addEventListener('click', function(e) {
      toggle(siteNav);
      e.preventDefault();
    });

    

    var tocToggle = document.getElementById('toctoggle');
    var toc = document.getElementById('toc');
    var articleMeta = document.getElementById('article-meta');
    var articleContent = document.getElementById('article-content');
    var articleMetaHeight = 0;
    var articleMetaMaxY = 0;
    var articleMetaMinY = 0;
    var articleContentPadding = 200;

    var tocLinks = document.querySelectorAll('.toc a');
    for (var t = 0; t < tocLinks.length; t++)
      tocLinks[t].addEventListener('click', onTocLinkClick);

    tocToggle.addEventListener('click', function(e) {
      toggle(toc);
      e.preventDefault();
    });

    toc.addEventListener('click', function(e) {
      if (e.target !== siteNav)
        toggle(toc, false);
    });

    function onTocLinkClick() {
      ga('send', 'event', 'Interactions', 'TOC', 'TOC Clicked');
    }

    function setMinScrollYFromMetaY() {
      var scrollPosition = window.scrollY;

      var articleMetaBounds = articleMeta.getBoundingClientRect();
      var articleMetaTop = Math.max(352,
          articleMetaBounds.top - 20 + scrollPosition);

      articleMetaHeight = articleMetaBounds.bottom - articleMetaBounds.top;
      articleMetaMinY = articleMetaTop;
    }

    function setMaxScrollYFromContentHeight() {

      var scrollPosition = window.scrollY;

      var articleContentBounds = articleContent.getBoundingClientRect();
      var articleContentTop = articleContentBounds.top + scrollPosition;
      var articleContentHeight = articleContentBounds.bottom - articleContentBounds.top;

      articleMetaMaxY = articleContentTop +
          articleContentHeight -
          articleMetaHeight -
          articleContentPadding;

    }

    function onScroll(e) {

      if (window.scrollY >= articleMetaMinY) {

        articleMeta.classList.add('sticky');

        var articleMetaTop = 22 - Math.max(0, window.scrollY - articleMetaMaxY);
        articleMeta.style.top = articleMetaTop + 'px';

      } else {
        articleMeta.classList.remove('sticky');
        articleMeta.style.top = 'auto';
      }
    }

    if (articleMeta.getBoundingClientRect) {
      setMinScrollYFromMetaY();
      setMaxScrollYFromContentHeight();
      document.addEventListener('scroll', onScroll);
      window.addEventListener('load', setMaxScrollYFromContentHeight, false);
    }

    
  })();
  </script>
  <script>
  (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
  (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
  m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
  })(window,document,'script','//www.google-analytics.com/analytics.js','ga');

  ga('create', 'UA-15028909-1', 'auto');
  ga('create', 'UA-49880327-4', 'auto', {'name': 'html5rocks'});

  ga('send', 'pageview');
  ga('html5rocks.send', 'pageview');

  </script>
   <!-- Google Tag Manager -->
<noscript><iframe src="//www.googletagmanager.com/ns.html?id=GTM-XXXX"
height="0" width="0" style="display:none;visibility:hidden"></iframe></noscript>
<script>(function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start':
new Date().getTime(),event:'gtm.js'});var f=d.getElementsByTagName(s)[0],
j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src=
'//www.googletagmanager.com/gtm.js?id='+i+dl;f.parentNode.insertBefore(j,f);
})(window,document,'script','dataLayer','GTM-MB3LRF');</script>
<!-- End Google Tag Manager -->
</body>
</html>
//


koh5_pano



Your browser does not support the HTML5 canvas element.


Drag mouse to navigate.

Navigation





17.Aug.2010, Martin Wengenmayer