demo介绍:将zip包解压到文件系统中,创建content文件夹,提供对文件系统操作的API以及将文件系统打包下载的功能。
完整demo请下载 http://download.csdn.net/detail/darcy_yuan/6307891
demo.js
/**
* about: zip, upzip, file system demo
* author: darcy_yuan
* dependency: zip.js, flate.js, infate.js
*
* ref:
* http://gildas-lormeau.github.io/zip.js/
* http://dev.w3.org/2009/dap/file-system/pub/FileSystem/
* http://dev.w3.org/2006/webapi/FileAPI/
* http://www.cnblogs.com/wzh2010/archive/2012/05/23/2514809.html
* http://www.html5rocks.com/zh/tutorials/file/filesystem/
*
* attention: all code should be executed in the callback funciton, because callback function will execute in the end.
* Chrome support only.
*/
(function(obj) {
var requestFileSystem = obj.webkitRequestFileSystem || obj.mozRequestFileSystem || obj.requestFileSystem;
//file system handler
var fs = null;
var xmlName = 'planner.xml';
var downloadName = 'planner.zip';
var contentDirectory = '/contents/';
(function() {
if (requestFileSystem) {
initFS();
}
})();
function initFS() {
requestFileSystem(window.TEMPORARY, 0.5*1024*1024*1024, function(filesystem) {
fs = filesystem;
//create contents directory
fs.root.getDirectory(contentDirectory, {create: true}, null, errorHandler);
}, errorHandler);
//test code
var fileInput = document.getElementById("file-input");
fileInput.addEventListener('change', function() {
upzipFile();
}, false);
var downloadButton = document.getElementById("download-button");
downloadButton.addEventListener('click', function() {
zipFile();
}, false);
var showXmlButton = document.getElementById("show-xml-button");
showXmlButton.addEventListener('click', function() {
getXml();
}, false);
var updateXmlButton = document.getElementById("update-xml-button");
updateXmlButton.addEventListener('click', function() {
var content = 'just for fun !';
updateXml(content);
}, false);
var getContentButton = document.getElementById("get-content-button");
getContentButton.addEventListener('click', function() {
var filename = document.getElementById("file-path").value;
getContent(filename);
}, false);
var fileInputAdd = document.getElementById("file-input-add");
fileInputAdd.addEventListener('change', function() {
addContent(fileInputAdd.files[0]);
}, false);
var deleteContentButton = document.getElementById("delete-content-button");
deleteContentButton.addEventListener('click', function() {
var filename = document.getElementById("file-path-delete").value;
deleteContent(filename);
}, false);
var cleanAllButton = document.getElementById("clean-all-button");
cleanAllButton.addEventListener('click', function() {
removeAll();
}, false);
//test code
}
function upzipFile() {
var fileInput = document.getElementById("file-input");
model_upzip.getEntries(fileInput.files[0], function(entries) {
//find the index of xml file
var index;
for(var i = 0;i < entries.length;i++) {
if(entries[i].filename == xmlName) {
index = i;
}
}
//if the xml doesn't exist
if(!index) {
onerror("incorrect planner file !");
return;
}
//add xml file
var xml_file = entries[index];
writer = new zip.BlobWriter();
entries[index].getData(writer, function(blob) {
writeNewFile(xml_file.filename, blob);
});
//add contents to directory :/contents
//delete xml file from entries
var entries_prefix = entries.slice(0,index);
var entries_suffix = entries.slice(index + 1);
var entries_content = entries_prefix.concat(entries_suffix);
for ( var i = 0;i < entries_content.length;i++) {
writer = new zip.BlobWriter();
// writer.id = i; //set id
entries_content[i].getData(writer,function(blob){
var path = contentDirectory + this.filename; //this.filename = entry.filename
writeNewFile(path, blob);
});
};
});
}
function zipFile() {
var downloadButton = document.getElementById("download-button");
model_zip.setCreationMethod('Blob');
var entries = new Array();
//get xml
getFileByDirectory('/',function(rootEntries){
entries = entries.concat(rootEntries[0]);
//get contents
getFileByDirectory(contentDirectory,function(contentsEntries){
entries = entries.concat(contentsEntries);
var files = new Array();
for(var i = 0;i < entries.length;i++) {
//transfer entry(FileEntry) to file(File)
entries[i].file(function(file){
files.push(file);
//push all file over
if (files.length == entries.length) {
//addFiles(files, oninit, onadd, onprogress, onend)
model_zip.addFiles(files,function(){},function(){},function(){},function(){
if (!downloadButton.download) {
//Saves the File or Blob to disk(Windows)
//http://msdn.microsoft.com/en-us/library/windows/apps/hh441122.aspx
if (typeof navigator.msSaveBlob == "function") {
model_zip.getBlob(function(blob) {
navigator.msSaveBlob(blob, downloadName);
});
} else {
model_zip.getBlobURL(function(blobURL) {
var clickEvent;
clickEvent = document.createEvent("MouseEvent");
clickEvent.initMouseEvent("click", true, true, window, 0, 0, 0, 0, 0, false, false, false, false, 0, null);
downloadButton.href = blobURL;
downloadButton.download = downloadName;
downloadButton.dispatchEvent(clickEvent);
});
event.preventDefault();
return false;
}
}
});
}
},function(){});
}
});
});
}
function getXml() {
//get xml from filesystem
readFileByName(xmlName,function(result){
alert(result);
});
}
function updateXml(content) {
//write new xml in file system
writeFile(xmlName, content);
}
function getContent(filename) {
//get content from file system
path = contentDirectory + filename;
readFileByName(path,function(result){
alert(result);
});
}
function addContent(file){
var path = contentDirectory +file.name;
writeFile(path,file);
}
function deleteContent(filename){
var path = contentDirectory +filename;
deleteFile(path);
}
//zip & upzip
function createTempFile_upzip(callback) {
var tmpFilename = "tmp.dat";
requestFileSystem(TEMPORARY, 4 * 1024 * 1024 * 1024, function(filesystem) {
function create() {
filesystem.root.getFile(tmpFilename, {
create : true
}, function(zipFile) {
callback(zipFile);
});
}
filesystem.root.getFile(tmpFilename, null, function(entry) {
entry.remove(create, create);
}, create);
});
}
function createTempFile_zip(callback) {
var tmpFilename = "tmp.zip";
//create temporary space
requestFileSystem(TEMPORARY, 4 * 1024 * 1024 * 1024, function(filesystem) {
function create() {
filesystem.root.getFile(tmpFilename, {
create : true
}, function(zipFile) {
callback(zipFile);
});
}
filesystem.root.getFile(tmpFilename, null, function(entry) {
entry.remove(create, create);
}, create);
});
}
var model_upzip = (function() {
var URL = obj.webkitURL || obj.mozURL || obj.URL;
return {
//get entry list
getEntries : function(file, onend) {
zip.createReader(new zip.BlobReader(file), function(zipReader) {
zipReader.getEntries(onend);
}, onerror);
},
//get one entry file
getEntryFile : function(entry, creationMethod, onend, onprogress) {
var writer, zipFileEntry;
function getData() {
entry.getData(writer, function(blob) {
var blobURL = creationMethod == "Blob" ? URL.createObjectURL(blob) : zipFileEntry.toURL();
onend(blobURL);
}, onprogress);
}
//get writer
if (creationMethod == "Blob") {
writer = new zip.BlobWriter();
getData();
} else {
createTempFile_upzip(function(fileEntry) {
zipFileEntry = fileEntry;
writer = new zip.FileWriter(zipFileEntry);
getData();
});
}
}
};
})();
var model_zip = (function() {
var zipFileEntry, zipWriter, writer, creationMethod, URL = obj.webkitURL || obj.mozURL || obj.URL;
return {
setCreationMethod : function(method) {
creationMethod = method;
},
addFiles : function addFiles(files, oninit, onadd, onprogress, onend) {
var addIndex = 0;
function nextFile() {
var file = files[addIndex];
zipWriter.add(file.name, new zip.BlobReader(file), function() {
addIndex++;
if (addIndex < files.length)
nextFile();
else
onend();
}
);
}
function createZipWriter() {
zip.createWriter(writer, function(writer) {
zipWriter = writer
nextFile();
}, onerror);
}
//2 ways to get zipWriter:BlobWriter FileWriter
//zipWriter != null , continue
if (zipWriter)
nextFile();
else if (creationMethod == "Blob") {
writer = new zip.BlobWriter();
createZipWriter();
} else {
createTempFile_zip(function(fileEntry) {
zipFileEntry = fileEntry;
writer = new zip.FileWriter(zipFileEntry);
createZipWriter();
});
}
},
getBlobURL : function(callback) {
zipWriter.close(function(blob) {
var blobURL = creationMethod == "Blob" ? URL.createObjectURL(blob) : zipFileEntry.toURL();
callback(blobURL);
zipWriter = null;
});
},
getBlob : function(callback) {
zipWriter.close(callback);
}
};
})();
//file system operation
//create a new directory of root
this.createDirectory = function (directoryName, callback) {
fs.root.getDirectory(directoryName, { create: true }, function (dirEntry) {
if (callback) callback(directoryName);
}, errorHandler);
}
//delete all files in a directory
this.removeDirectoryAll = function (directoryName, callback) {
fs.root.getDirectory(directoryName, {}, function (dirEntry) {
dirEntry.removeRecursively(function () {
if (callback) callback(directoryName);
}, errorHandler);
}, errorHandler);
}
//create a Directory by fileName
this.createFileWithPath = function (fileName, callback) {
var paths = fileName.split('/');
createDir(fs.root, paths);
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);
}
//Log.debug("createDir " + folders[0]);
if (folders.length == 1 && folders[0].split('.').length > 1) {
rootDirEntry.getFile(folders[0], { create: true, exclusive: false }, function (fileEntry) {
//Log.debug("create file " + fileEntry.fullPath);
if (callback) callback(fileEntry);
}, errorHandler);
}
else {
rootDirEntry.getDirectory(folders[0], { create: true, exclusive: false }, function (dirEntry) {
// Recursively add the new subfolder (if we still have another to create).
if (folders.length) {
createDir(dirEntry, folders.slice(1));
}
}, errorHandler);
}
};
}
//write a file to a direcotry
this.writeNewFile = function (fileName, content, callback) {
createFileWithPath(fileName, function (fileEntry) {
// Log.debug("write file " + fileEntry.fullPath);
fileEntry.createWriter(function (fileWriter) {
fileWriter.onwriteend = function (e) {
if (callback) callback(fileEntry.fullPath);
};
fileWriter.onerror = function (e) {
if (callback) callback(fileEntry.fullPath, e);
};
var bb = new Blob([content], { type: "text/plain" }); // Note: window.WebKitBlobBuilder in Chrome 12.
fileWriter.write(bb);
}, errorHandler);
});
}
//get a file by fileName
this.readFileByName = function (fileName, callback) {
fs.root.getFile(fileName, {}, function (fileEntry) {
fileEntry.file(function (file) {
var reader = new FileReader();
reader.onloadend = function (e) {
if (callback) callback(this.result);
};
reader.readAsText(file);
}, errorHandler);
}, function (e) {
if (callback) callback("0");
});
}
//delete a file by fileName
this.deleteFile = function (fileName, callback) {
fs.root.getFile(fileName, { create: false }, function (fileEntry) {
fileEntry.remove(function () {
if (callback) callback(fileName);
}, errorHandler);
}, errorHandler);
};
//remove and write a file to a directory
this.writeFile = function (fileName, content, callback) {
fs.root.getFile(fileName, {}, function (fileEntry) {
fileEntry.remove(function () {
writeNewFile(fileName, content, callback);
});
}, function () {
writeNewFile(fileName, content, callback);
});
};
this.getFileByDirectory = function (directoryName,callback) {
fs.root.getDirectory(directoryName, {}, function (dirEntry) {
var dirReader = dirEntry.createReader();
var entries = [];
// Call the reader.readEntries() until no more results are returned.
var readEntries = function() {
dirReader.readEntries (function(results) {
if (results.length) {
entries = entries.concat(toArray(results));
readEntries();
} else {
callback(entries);
}
}, errorHandler);
};
readEntries(); // Start reading dirs.
}, errorHandler);
};
this.removeAll = function() {
var dirReader = fs.root.createReader();
dirReader.readEntries(function(entries) {
for (var i = 0, entry; entry = entries[i]; ++i) {
if (entry.isDirectory) {
entry.removeRecursively(function() {}, errorHandler);
} else {
entry.remove(function() {}, errorHandler);
}
}
}, errorHandler);
};
function errorHandler(e) {
var msg = '';
switch (e.code) {
case FileError.QUOTA_EXCEEDED_ERR:
msg = 'QUOTA_EXCEEDED_ERR';
break;
case FileError.NOT_FOUND_ERR:
msg = 'NOT_FOUND_ERR';
break;
case FileError.SECURITY_ERR:
msg = 'SECURITY_ERR';
break;
case FileError.INVALID_MODIFICATION_ERR:
msg = 'INVALID_MODIFICATION_ERR';
break;
case FileError.INVALID_STATE_ERR:
msg = 'INVALID_STATE_ERR';
break;
default:
msg = 'Unknown Error';
break;
};
}
function onerror(message) {
alert(message);
}
function toArray(list) {
return Array.prototype.slice.call(list || [], 0);
}
})(this);
zip.js 修改部分
Entry.prototype.getData = function(writer, onend, onprogress, checkCrc32) {
var that = this, worker;
function terminate(callback, param) {
if (worker)
worker.terminate();
worker = null;
if (callback)
// callback.call(writer, param);
callback.call(that, param);
}
function testCrc32(crc32) {
var dataCrc32 = getDataHelper(4);
dataCrc32.view.setUint32(0, crc32);
return that.crc32 == dataCrc32.view.getUint32(0);
}
function getWriterData(uncompressedSize, crc32) {
if (checkCrc32 && !testCrc32(crc32))
onreaderror();
else
writer.getData(function(data) {
terminate(onend, data);
});
}
function onreaderror() {
terminate(onerror, ERR_READ_DATA);
}
function onwriteerror() {
terminate(onerror, ERR_WRITE_DATA);
}
reader.readUint8Array(that.offset, 30, function(bytes) {
var data = getDataHelper(bytes.length, bytes), dataOffset;
if (data.view.getUint32(0) != 0x504b0304) {
onerror(ERR_BAD_FORMAT);
return;
}
readCommonHeader(that, data, 4, false, onerror);
dataOffset = that.offset + 30 + that.filenameLength + that.extraFieldLength;
writer.init(function() {
if (that.compressionMethod === 0)
copy(reader, writer, dataOffset, that.compressedSize, checkCrc32, getWriterData, onprogress, onreaderror, onwriteerror);
else
worker = inflate(reader, writer, dataOffset, that.compressedSize, checkCrc32, getWriterData, onprogress, onreaderror, onwriteerror);
}, onwriteerror);
}, onreaderror);
};
function seekEOCDR(offset, entriesCallback) {
reader.readUint8Array(reader.size - offset, offset, function(bytes) {
var dataView = getDataHelper(bytes.length, bytes).view;
if (dataView.getUint32(0) != 0x504b0506) {
seekEOCDR(offset + 1, entriesCallback);
} else {
entriesCallback(dataView);
}
}, function() {
onerror(ERR_READ);
});
}
return {
getEntries : function(callback) {
if (reader.size < 22) {
onerror(ERR_BAD_FORMAT);
return;
}
// look for End of central directory record
seekEOCDR(22, function(dataView) {
var datalength, fileslength;
datalength = dataView.getUint32(16, true);
fileslength = dataView.getUint16(8, true);
reader.readUint8Array(datalength, reader.size - datalength, function(bytes) {
var i, index = 0, entries = [], entry, filename, comment, data = getDataHelper(bytes.length, bytes);
for (i = 0; i < fileslength; i++) {
entry = new Entry();
if (data.view.getUint32(index) != 0x504b0102) {
onerror(ERR_BAD_FORMAT);
return;
}
readCommonHeader(entry, data, index + 6, true, onerror);
entry.commentLength = data.view.getUint16(index + 32, true);
entry.directory = ((data.view.getUint8(index + 38) & 0x10) == 0x10);
entry.offset = data.view.getUint32(index + 42, true);
filename = getString(data.array.subarray(index + 46, index + 46 + entry.filenameLength));
entry.filename = ((entry.bitFlag & 0x0800) === 0x0800) ? decodeUTF8(filename) : decodeASCII(filename);
if (!entry.directory && entry.filename.charAt(entry.filename.length - 1) == "/")
entry.directory = true;
comment = getString(data.array.subarray(index + 46 + entry.filenameLength + entry.extraFieldLength, index + 46
+ entry.filenameLength + entry.extraFieldLength + entry.commentLength));
entry.comment = ((entry.bitFlag & 0x0800) === 0x0800) ? decodeUTF8(comment) : decodeASCII(comment);
entries.push(entry);
index += 46 + entry.filenameLength + entry.extraFieldLength + entry.commentLength;
}
callback(entries);
}, function() {
onerror(ERR_READ);
});
});
},
close : function(callback) {
if (callback)
callback();
}
};