基于javascript的压缩和解压缩以及文件系统的demo

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();
			}
		};



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值