https://ybzj.neocities.org/tphdb/ 使用作者链接,一下仅作备份,需要放到本地或者服务器环境 <!DOCTYPE html> <html> <head> <meta charset="utf-8" name="viewport" content="width=device-width, initial-scale=1"> <title>图片化打包</title> <style> .pad1{ padding:0.5rem 0; border-bottom:1px solid #ccc; } summary{ font-size:1rem; padding:0rem 0.5rem; } details{ padding:0.5rem; margin-top:0.5rem; outline:1px solid #ccc; } .pad2{ padding-top:0.5rem; } body{ padding:0 0.75rem; } </style> </head> <body> <h1>图片化打包</h1> <details open> <summary>使用说明</summary> <div> 这是一个用来方便地在社交平台上传输文件的程序,原理是将图片与文件结合,在发送图片的同时发送文件。<br /><span style="color:#ff4d00">使用此程序的"提取文件"功能所获得的文件,其来源均是此程序的其他使用者,与此程序本身没有任何关系。<br />此程序的所有图片处理功能都在本地进行,不会将任何文件上传至网上。<br />此程序加密功能来源于浏览器API,此程序不提供任何对于用户文件保密性的担保,也对此不负任何责任。<br />此程序的本意是为社交平台用户提供便利,请勿用此程序进行非法行为,否则作者概不负责。</span> </div> <div> 此程序不兼容图片文件夹 </div> </details> <details> <summary>打包文件</summary> <div class="pad2"> 选择表图  <input id="ipt3" type="file" accept="image/*" multiple /> </div> <div id="encodeipt" class="pad2"> 选择文件  </div> <div class="pad2"> 加密密码  <input style="width:150px;height:1.25rem" type="text" id="encodepassword" placeholder="请输入密码" />  </div> <div class="pad2"> 分片数量  <input style="width:75px" type="number" id="slice" value="1"/> </div> <div class="pad2"> <input checked type="checkbox" id="check1">显示备注</input> <input type="text" id="text" style="width:150px;height:1.25rem" value="图片化打包" /> <br /><input checked type="checkbox" id="check2">显示序号</input> <br /><input type="checkbox" id="check3">显示文件名</input> <br /><input type="checkbox" id="check4">显示文件大小</input> </div> <div class="pad2"> <button id="pack"> 打包 </button> <span id="packinfo" style="display:none">正在打包</span> </div> <div class="pad2" id="display"> </div> </details> <details> <summary>提取文件</summary> <div id="decodeipt" class="pad1"> <button id="clear"> 清空 </button>  </div> <div class="pad1"> <span id="failbutton"> 失败 </span>  <span id="pendingbutton">待解密</span>  <span id="assemblingbutton">待组装</span>  <span id="successbutton"> 成功 </span> </div> <div id="fail"> <div class="pad1"> 以下图片不是图片化打包! </div> </div> <div id="pending"> <div class="pad1"> <input style="width:150px;height:1.25rem" type="text" id="decodepassword" placeholder="请输入密码" />  <button id="decode"> 确定 </button>  <span id="decodeinfo"></span> </div> </div> <div id="assembling"> </div> <div id="success"> </div> </details> <script> function gebi(a){ return document.getElementById(a) } let showlist=[gebi("fail"),gebi("pending"),gebi("assembling"),gebi("success")] let buttonlist=[gebi("failbutton"),gebi("pendingbutton"),gebi("assemblingbutton"),gebi("successbutton")] showlist.map(x=>x.style.display="none") buttonlist.map((x,i)=>{ x.style.outline="1px solid #ccc" x.style.padding="0.25rem 0.5rem" x.onclick=()=>{ showlist.map(x=>x.style.display="none") buttonlist.map(x=>x.style.background="#fff") showlist[i].style.display="block" buttonlist[i].style.background="#eee" } }) buttonlist[1].click() function sizec(bytes){ let i=0 let list=["B","KB","MB","GB","TB"] while(bytes/Math.pow(1024,i)>=1000){ i++ } bytes=bytes/Math.pow(1024,i) if(bytes>100){ bytes=Math.round(bytes) }else if(bytes>10){ bytes=Math.round(bytes*10)/10 }else{ bytes=Math.round(bytes*100)/100 } return bytes+list[i] } let checklist=[gebi("check1"),gebi("check2"),gebi("check3"),gebi("check4")] </script> <script> //处理png的数据块 ;(()=>{ let png=window.png=new Object() ;(()=> { let table = [0x00000000,0x77073096,0xEE0E612C,0x990951BA,0x076DC419,0x706AF48F,0xE963A535,0x9E6495A3,0x0EDB8832,0x79DCB8A4,0xE0D5E91E,0x97D2D988,0x09B64C2B,0x7EB17CBD,0xE7B82D07,0x90BF1D91,0x1DB71064,0x6AB020F2,0xF3B97148,0x84BE41DE,0x1ADAD47D,0x6DDDE4EB,0xF4D4B551,0x83D385C7,0x136C9856,0x646BA8C0,0xFD62F97A,0x8A65C9EC,0x14015C4F,0x63066CD9,0xFA0F3D63,0x8D080DF5,0x3B6E20C8,0x4C69105E,0xD56041E4,0xA2677172,0x3C03E4D1,0x4B04D447,0xD20D85FD,0xA50AB56B,0x35B5A8FA,0x42B2986C,0xDBBBC9D6,0xACBCF940,0x32D86CE3,0x45DF5C75,0xDCD60DCF,0xABD13D59,0x26D930AC,0x51DE003A,0xC8D75180,0xBFD06116,0x21B4F4B5,0x56B3C423,0xCFBA9599,0xB8BDA50F,0x2802B89E,0x5F058808,0xC60CD9B2,0xB10BE924,0x2F6F7C87,0x58684C11,0xC1611DAB,0xB6662D3D,0x76DC4190,0x01DB7106,0x98D220BC,0xEFD5102A,0x71B18589,0x06B6B51F,0x9FBFE4A5,0xE8B8D433,0x7807C9A2,0x0F00F934,0x9609A88E,0xE10E9818,0x7F6A0DBB,0x086D3D2D,0x91646C97,0xE6635C01,0x6B6B51F4,0x1C6C6162,0x856530D8,0xF262004E,0x6C0695ED,0x1B01A57B,0x8208F4C1,0xF50FC457,0x65B0D9C6,0x12B7E950,0x8BBEB8EA,0xFCB9887C,0x62DD1DDF,0x15DA2D49,0x8CD37CF3,0xFBD44C65,0x4DB26158,0x3AB551CE,0xA3BC0074,0xD4BB30E2,0x4ADFA541,0x3DD895D7,0xA4D1C46D,0xD3D6F4FB,0x4369E96A,0x346ED9FC,0xAD678846,0xDA60B8D0,0x44042D73,0x33031DE5,0xAA0A4C5F,0xDD0D7CC9,0x5005713C,0x270241AA,0xBE0B1010,0xC90C2086,0x5768B525,0x206F85B3,0xB966D409,0xCE61E49F,0x5EDEF90E,0x29D9C998,0xB0D09822,0xC7D7A8B4,0x59B33D17,0x2EB40D81,0xB7BD5C3B,0xC0BA6CAD,0xEDB88320,0x9ABFB3B6,0x03B6E20C,0x74B1D29A,0xEAD54739,0x9DD277AF,0x04DB2615,0x73DC1683,0xE3630B12,0x94643B84,0x0D6D6A3E,0x7A6A5AA8,0xE40ECF0B,0x9309FF9D,0x0A00AE27,0x7D079EB1,0xF00F9344,0x8708A3D2,0x1E01F268,0x6906C2FE,0xF762575D,0x806567CB,0x196C3671,0x6E6B06E7,0xFED41B76,0x89D32BE0,0x10DA7A5A,0x67DD4ACC,0xF9B9DF6F,0x8EBEEFF9,0x17B7BE43,0x60B08ED5,0xD6D6A3E8,0xA1D1937E,0x38D8C2C4,0x4FDFF252,0xD1BB67F1,0xA6BC5767,0x3FB506DD,0x48B2364B,0xD80D2BDA,0xAF0A1B4C,0x36034AF6,0x41047A60,0xDF60EFC3,0xA867DF55,0x316E8EEF,0x4669BE79,0xCB61B38C,0xBC66831A,0x256FD2A0,0x5268E236,0xCC0C7795,0xBB0B4703,0x220216B9,0x5505262F,0xC5BA3BBE,0xB2BD0B28,0x2BB45A92,0x5CB36A04,0xC2D7FFA7,0xB5D0CF31,0x2CD99E8B,0x5BDEAE1D,0x9B64C2B0,0xEC63F226,0x756AA39C,0x026D930A,0x9C0906A9,0xEB0E363F,0x72076785,0x05005713,0x95BF4A82,0xE2B87A14,0x7BB12BAE,0x0CB61B38,0x92D28E9B,0xE5D5BE0D,0x7CDCEFB7,0x0BDBDF21,0x86D3D2D4,0xF1D4E242,0x68DDB3F8,0x1FDA836E,0x81BE16CD,0xF6B9265B,0x6FB077E1,0x18B74777,0x88085AE6,0xFF0F6A70,0x66063BCA,0x11010B5C,0x8F659EFF,0xF862AE69,0x616BFFD3,0x166CCF45,0xA00AE278,0xD70DD2EE,0x4E048354,0x3903B3C2,0xA7672661,0xD06016F7,0x4969474D,0x3E6E77DB,0xAED16A4A,0xD9D65ADC,0x40DF0B66,0x37D83BF0,0xA9BCAE53,0xDEBB9EC5,0x47B2CF7F,0x30B5FFE9,0xBDBDF21C,0xCABAC28A,0x53B39330,0x24B4A3A6,0xBAD03605,0xCDD70693,0x54DE5729,0x23D967BF,0xB3667A2E,0xC4614AB8,0x5D681B02,0x2A6F2B94,0xB40BBE37,0xC30C8EA1,0x5A05DF1B,0x2D02EF8D]; let crc32 = png.crc32 = (arr,crc)=>{ crc = crc || 0; let n = 0; let x = 0; crc ^= -1; for(let i = 0 ; i < arr.length; i++ ) { n = ( crc ^ arr[i] ) & 0xFF; x = table[n]; crc = ( crc >>> 8 ) ^ x; } crc ^= -1; return crc } })() function crc32arr(arr){ return arr.reduce((a,b)=>png.crc32(b,a),0) } function concatuint8array(arrays){ let length=arrays.reduce((a,b)=>a+b.length,0) let result=new Uint8Array(length) let start=0 arrays.map(x=>{ result.set(x,start) start+=x.length }) return result } function slicestring(arr,start,length){ let result="" for(let i=0;i<length;i++){ result+=String.fromCharCode(arr[i+start]) } return result } function stringtoarray(str){ return str.split("").map(x=>x.charCodeAt(0)) } function stringtouint8array(str,ifzero){ let arr=new Uint8Array(str.length+(ifzero?1:0)) for(let i=0;i<str.length;i++){ arr[i]=str.charCodeAt(i) } return arr } function writestring(arr,str,start){ start=start||0 for(let i=0;i<str.length;i++){ arr[start+i]=str.charCodeAt(i) } return arr } function getuint32(arr,start){ let result=(arr[start]<<24)|(arr[start+1]<<16)|(arr[start+2]<<8)|arr[start+3] return (result<0)?(result+4294967296):result } function createint32(num){ return[num>>>24,num>>>16&0xff,num>>>8&0xff,num&0xff] } function readasuint8array(blob,returnfunc){ let fr=new FileReader() fr.readAsArrayBuffer(blob) fr.onload=(e)=>{ returnfunc(new Uint8Array(e.target.result)) } } function extract(arr,code){ //png文件magic number //89504e470d0a1a0a if(getuint32(arr,0)!=0x89504e47){ return false } let i=8 let result=[] while(i<arr.length){ let length=getuint32(arr,i) let arrslice=arr.slice(i+8,i+8+length) arrslice.chunkname=slicestring(arr,i+4,4) result.push(arrslice) i+=length+12 } return result } function assemble(arr){ let process=arr.map(a=>{ let lengthchunk=createint32(a.length) let namechunk=stringtoarray(a.chunkname) let crcchunk=createint32(crc32arr([namechunk,a])) return concatuint8array([lengthchunk,namechunk,a,crcchunk]) }) return concatuint8array([[0x89,0x50,0x4e,0x47,0x0d,0x0a,0x1a,0x0a]].concat(process)) } png.readasuint8array=readasuint8array png.extract=extract png.assemble=assemble })(); //基础加密功能 ;(()=>{ if(!window.crypto.subtle){ alert("发生错误: Crypto API 不可用") } let subtle=window.crypto.subtle let tankcrypto=window.tankcrypto=new Object() function stringtouint8array(str,ifzero){ let arr=new Uint8Array(str.length+(ifzero?1:0)) for(let i=0;i<str.length;i++){ arr[i]=str.charCodeAt(i) } return arr } /*utf8*/ function utf8Encode(string){ var utftext = ""; for (var n = 0; n < string.length; n++) { var c = string.charCodeAt(n); if (c < 128) { utftext += String.fromCharCode(c); } else if ((c > 127) && (c < 2048)) { utftext += String.fromCharCode((c >> 6) | 192); utftext += String.fromCharCode((c & 63) | 128); } else { utftext += String.fromCharCode((c >> 12) | 224); utftext += String.fromCharCode(((c >> 6) & 63) | 128); utftext += String.fromCharCode((c & 63) | 128); } } return utftext; } function utf8Decode(inputStr){ var outputStr = ""; var code1, code2, code3, code4; for (var i = 0; i < inputStr.length; i++) { code1 = inputStr.charCodeAt(i); if (code1 < 128) { outputStr += String.fromCharCode(code1); } else if (code1 < 224) { code2 = inputStr.charCodeAt(++i); outputStr += String.fromCharCode(((code1 & 31) << 6) | (code2 & 63)); } else if (code1 < 240) { code2 = inputStr.charCodeAt(++i); code3 = inputStr.charCodeAt(++i); outputStr += String.fromCharCode(((code1 & 15) << 12) | ((code2 & 63) << 6) | (code3 & 63)); } else { code2 = inputStr.charCodeAt(++i); code3 = inputStr.charCodeAt(++i); code4 = inputStr.charCodeAt(++i); outputStr += String.fromCharCode(((code1 & 7) << 18) | ((code2 & 63) << 12) | ((code3 & 63) << 6) | (code2 & 63)); } } return outputStr; } let sha256=tankcrypto.sha256=function(str){ let input=stringtouint8array(utf8Encode(str)) return subtle.digest("SHA-256",input) } let rawsha256=tankcrypto.rawsha256=function(buffer){ return subtle.digest("SHA-256",buffer) } let createkey=tankcrypto.createkey=function(str){ let input=stringtouint8array(utf8Encode(str)) return subtle.digest("SHA-256",input).then((digest)=>{ return subtle.importKey("raw",digest,{name:"AES-CBC"},false,["encrypt","decrypt"]) }) } let createkey128=tankcrypto.createkey128=function(str){ let input=stringtouint8array(utf8Encode(str)) return subtle.digest("SHA-256",input).then((digest)=>{ return subtle.importKey("raw",digest.slice(0,16),{name:"AES-CBC"},false,["encrypt","decrypt"]) }) } let importkey=tankcrypto.importkey=function(buffer){ return subtle.importKey("raw",buffer,{name:"AES-CBC"},false,["encrypt","decrypt"]) } let encrypt=tankcrypto.encrypt=function(key,iv,data){ return subtle.encrypt({name:"AES-CBC",iv:iv},key,data) } let decrypt=tankcrypto.decrypt=function(key,iv,data){ return subtle.decrypt({name:"AES-CBC",iv:iv},key,data) } tankcrypto.utf8Encode=utf8Encode tankcrypto.utf8Decode=utf8Decode })(); </script> <script> function concatuint8array(arrays){ let length=arrays.reduce((a,b)=>a+b.length,0) let result=new Uint8Array(length) let start=0 arrays.map(x=>{ result.set(x,start) start+=x.length }) return result } function stringtouint8array(str,ifzero){ let arr=new Uint8Array(str.length+(ifzero?1:0)) for(let i=0;i<str.length;i++){ arr[i]=str.charCodeAt(i) } return arr } function arraytostring(arr){ let str="" for(let i=0;i<arr.length;i++){ str=str+String.fromCharCode(arr[i]) } return str } let utf8Decode=tankcrypto.utf8Decode let utf8Encode=tankcrypto.utf8Encode </script> <script> //带校验的奇怪加密方法 function allenc(key,data){ let iv1buffer =window.crypto.getRandomValues(new Uint8Array(16)) let randomdata=window.crypto.getRandomValues(new Uint8Array(968)) let iv2buffer =randomdata.slice(-16) let key2buffer=randomdata.slice(-48,-16) return new Promise((resolve,reject)=>{ Promise.all([ window.tankcrypto.importkey(key2buffer).then(key2=>{ return window.tankcrypto.encrypt(key2,iv2buffer,data) }), window.tankcrypto.rawsha256(randomdata) ]).then(arr=>{ let encryptedorigin=new Uint8Array(arr[0]) let hash=new Uint8Array(arr[1]) let meta=concatuint8array([hash,randomdata]) window.tankcrypto.encrypt(key,iv1buffer,meta).then(encryptedmetabuffer=>{ let encryptedmeta=new Uint8Array(encryptedmetabuffer) let result=concatuint8array([iv1buffer,encryptedmeta,encryptedorigin]) result.extra={key:key2buffer,iv2buffer} resolve(result) }).catch(reject) }).catch(reject) }) } //解密,顺带校验 function alldec(key,data){ return new Promise((resolve,reject)=>{ let iv1=data.slice(0,16) let part1=data.slice(16,1024) window.tankcrypto.decrypt(key,iv1,part1).then(decrypted1=>{ let hash=new Uint8Array(decrypted1.slice(0,32)) window.tankcrypto.rawsha256(decrypted1.slice(32)) .then(rawhash1=>{ let hash1=new Uint8Array(rawhash1) let ifcorrect=hash1.every((v,x)=>v==hash[x]) if(ifcorrect){ let iv2=decrypted1.slice(-16) let key2buffer=decrypted1.slice(-48,-16) window.tankcrypto.importkey(key2buffer).then(key2=>{ return window.tankcrypto.decrypt(key2,iv2,data.slice(1024)) }).then(decrypted=>{ resolve(new Uint8Array(decrypted)) }).catch(reject) }else{ reject("incorrect password") } }).catch(reject) }).catch(reject) }) } </script> <script> function dataURLtoArray(dataurl){ let arr = dataurl.split(','), _arr = arr[1], bstr = atob(_arr), n = bstr.length, u8arr = new Uint8Array(n) while (n--) { u8arr[n] = bstr.charCodeAt(n) } return u8arr } function genpngarr(img,text){ let w=img.width let h=img.height if(w*h>100000){ let s=Math.sqrt(100000/w/h) w=w*s|0 h=h*s|0 } let cvs=document.createElement("canvas") let ctx=cvs.getContext("2d") cvs.width=w cvs.height=h ctx.drawImage(img,0,0,w,h) if(text){ ctx.fillStyle="#000" ctx.strokeStyle="#fff" ctx.lineWidth=4 ctx.font="20px sans-serif" ctx.textBaseline="middle" for(let i=0;i<text.length;i++){ if(i==0){ ctx.textAlign="right" ctx.strokeText(text[i],w-5,15,w-10) ctx.fillText(text[i],w-5,15,w-10) ctx.textAlign="left" }else{ ctx.strokeText(text[i],5,h+10-i*25,w-10) ctx.fillText(text[i],5,h+10-i*25,w-10) } } } return cvs.toDataURL() } //随机默认表图 function randompngarr(text){ let cvs=document.createElement("canvas") let ctx=cvs.getContext("2d") cvs.width=cvs.height=420 ctx.fillStyle="#fff" ctx.fillRect(0,0,420,420) let theta=Math.random()*Math.PI*2 ctx.fillStyle="rgb("+[Math.cos(theta),Math.cos(theta-Math.PI*2/3),Math.cos(theta+Math.PI*2/3)].map(x=>x*(Math.random()+1)*64+96+Math.random()*64)+")" ctx.shadowColor="#bfbfbf" ctx.shadowBlur=15 ctx.shadowOffsetX=ctx.shadowOffsetY=10 ctx.moveTo(375,0) ctx.beginPath() let n=3 for(let t=0;t<Math.PI*2;t+=0.05){ let length=1/Math.pow(Math.pow(Math.abs(Math.cos(t)),n)+Math.pow(Math.abs(Math.sin(t)),n),1/n) let x=length*Math.cos(t) let y=length*Math.sin(t) ctx.lineTo(x*165+210,y*165+210) } ctx.closePath() ctx.fill() ctx.shadowColor="rgba(0,0,0,0)" ctx.setTransform(1,0,0,1,60,60) ctx.fillStyle=ctx.strokeStyle="#fff" ctx.lineJoin="round" ctx.lineWidth=16 ctx.beginPath() ctx.moveTo(110,50) ctx.lineTo(225,50) ctx.lineTo(225,250) ctx.lineTo(75,250) ctx.lineTo(75,85) ctx.closePath() ctx.stroke() ctx.fillRect(105,110,90,16) ctx.fillRect(105,155,90,16) ctx.fillRect(105,200,90,16) ctx.setTransform(1,0,0,1,0,0) if(text){ ctx.fillStyle="#000" ctx.strokeStyle="#fff" ctx.lineWidth=4 ctx.font="20px sans-serif" ctx.textBaseline="middle" for(let i=0;i<text.length;i++){ if(i==0){ ctx.textAlign="right" ctx.strokeText(text[i],415,15,410) ctx.fillText(text[i],415,15,410) ctx.textAlign="left" }else{ ctx.strokeText(text[i],5,430-i*25,410) ctx.fillText(text[i],5,430-i*25,410) } } } return cvs.toDataURL() } //进:加密后uarr //出:png的uarr function picenc(img,data,key,textarr){ let dataurl; if(img){ dataurl=genpngarr(img,textarr) }else{ dataurl=randompngarr(textarr) } let dataarr=dataURLtoArray(dataurl) let splited=png.extract(dataarr) let end=splited.pop() return new Promise((resolve,reject)=>{ allenc(key,data).then(encrypted=>{ encrypted.chunkname="dSIG" splited.push(encrypted) splited.push(end) let assembled=png.assemble(splited) resolve(assembled) }).catch(reject) }) } //提取数据块内容 function picextract(data){ let splited=png.extract(data) let i=0 if(!splited){ return {fail:true} } while(splited[++i].chunkname!="dSIG"){ if(i>=splited.length-1){ return {fail:true} } } return splited[i] } </script> <script> //file读成uarr //返回promise function readfile(file){ return new Promise((resolve,reject)=>{ let filereader=new FileReader() filereader.readAsArrayBuffer(file) filereader.onload=(e)=>{ let result=new Uint8Array(e.target.result) result.metadata={ name:utf8Encode(file.name), mime:file.type, length:result.length } resolve(result) } filereader.onerror=reject }) } //进:file,出:待加密的东西 //返回promise function wrap(filearr,slice){ return Promise.all(Array.from(filearr).map(file=>readfile(file))) .then(arr=>{ let result=[] let dataarr=concatuint8array(arr) let length=dataarr.length if(slice<0){ slice=Math.ceil(-length/slice) } let meta={ id:"A00"+Math.random().toString(16).slice(2), slice:slice, data:arr.map(x=>x.metadata) } for(let i=0;i<slice;i++){ let slicebyte=dataarr.slice(Math.floor(length*i/slice),Math.floor(length*(i+1)/slice)) meta.count=i meta.length=slicebyte.length let metaarr=stringtouint8array(JSON.stringify(meta),true) result.push(concatuint8array([metaarr,slicebyte])) delete meta.data } return result }) } //同步 //分离meta与data function unwrapsingle(arr){ let i=0 while(arr[++i]!=0); let meta=JSON.parse(arraytostring(arr.slice(0,i))) let data=arr.slice(i+1) if(meta.length){ data=data.slice(0,meta.length) } data.meta=meta return data } //拼接分离出的data,转成file function unwraptofile(dataarr){ let block=concatuint8array(dataarr) let filemeta=dataarr[0].meta.data let pointer=0 let result=[] for(let j=0;j<filemeta.length;j++){ let filebuffer=block.buffer.slice(pointer,pointer+filemeta[j].length) pointer+=filemeta[j].length let name=utf8Decode(filemeta[j].name) let mime=filemeta[j].mime let file=new File([filebuffer],name,{type:mime}) result.push(file) } return result } </script> <script> //创建缩略图 function createresize(file){ let imgelement=document.createElement("img") imgelement.style.width="120px" file.imgelement=imgelement let cvs=document.createElement("canvas") let ctx=cvs.getContext("2d") cvs.width=cvs.height=250 let img=new Image() img.src=URL.createObjectURL(file) img.onload=()=>{ URL.revokeObjectURL(img.src) ctx.drawImage(img,0,0,250,250) imgelement.src=cvs.toDataURL("image/jpeg",0.5) } } let assembler={ div:document.createElement("div"), adiv:document.createElement("div"), pdiv:document.createElement("div"), fdiv:document.createElement("div"), assembling:{}, pending:[], fail:[], srclist:[] } assembler.change=function(){ assembler.adiv.innerHTML="" assembler.pdiv.innerHTML="" assembler.fdiv.innerHTML="" assembler.pending.map(x=>assembler.pdiv.appendChild(x.imgelement)) assembler.fail.map(x=>assembler.fdiv.appendChild(x.imgelement)) for(let id in assembler.assembling){ let assembling=assembler.assembling[id] if(!assembling.success){ let div=document.createElement("div") div.style.outline="1px solid #ccc" let div1=document.createElement("div") div.appendChild(div1) let slice=assembling.array.length let count=0 assembling.array.map(x=>{ count++ div.appendChild(x.imgelement) }) div1.innerText="进度 "+count+"/"+slice assembler.adiv.appendChild(div) } } } assembler.push=function(arr/*of files*/){ arr=Array.from(arr) arr.map(x=>createresize(x)) return Promise.all(arr.map(x=>{ return readfile(x).then(y=>{ let result=picextract(y) result.imgelement=x.imgelement return result }) })).then(resultarr=>{ let pendingpart=resultarr.filter(x=>!x.fail) assembler.pending=assembler.pending.concat(pendingpart) let failpart=resultarr.filter(x=>x.fail) assembler.fail=assembler.fail.concat(failpart) assembler.change() return [pendingpart.length,failpart.length] }) } assembler.trydec=function(key){ return Promise.all(assembler.pending.map(x=>alldec(key,x) .then(result=>{ let r=unwrapsingle(result) r.success=true r.imgelement=x.imgelement return r },(e)=>{ return x }))).then(arr=>{ let successpart=arr.filter(x=>x.success) let failpart=arr.filter(x=>!x.success) if(successpart.length==0){ return 0 } assembler.pending=failpart successpart.map(x=>assembler.assemble(x)) assembler.change() return successpart.length }) } assembler.assemble=function(data/*of single slice*/){ if(!assembler.assembling[data.meta.id]){ assembler.assembling[data.meta.id]={ array:new Array(data.meta.slice) } } let assembling=assembler.assembling[data.meta.id] if(assembling.success){ return } assembling.array[data.meta.count]=data let flag=true for(let i=0;i<assembling.array.length;i++){ flag=(!!assembling.array[i])&&flag } if(flag){ assembling.success=true //强制异步,防止太慢影响解密结果显示 requestAnimationFrame(()=>{ requestAnimationFrame(()=>{ let files=unwraptofile(assembling.array) assembler.createdisplay(files) delete assembling.array }) }) } } assembler.createdisplay=function(arr/*of files*/){ let div=document.createElement("div") div.style.outline="1px solid #ccc" div.style.paddingBottom="0.5rem" arr.map(f=>div.appendChild(assembler.createsingledisplay(f))) assembler.div.appendChild(div) } assembler.createsingledisplay=function(b){ let src=URL.createObjectURL(b) assembler.srclist.push(b) let div=document.createElement("div") div.style.paddingTop="0.5rem" let div2=document.createElement("div") div2.style.wordBreak="break-all" div.appendChild(div2) let a=document.createElement("a") a.innerText="保存" a.href=src a.download=b.name div2.appendChild(a) let span=document.createElement("span") span.innerText=b.name span.innerHTML=" "+span.innerHTML div2.appendChild(span) if(b.type.indexOf("image")>-1){ let img=document.createElement("img") img.style.maxWidth="100%" img.src=src div.appendChild(img) } if(b.type.indexOf("video")>-1){ let img=document.createElement("video") img.controls=true img.style.maxWidth="100%" img.src=src div.appendChild(img) } return div } </script> <script> function make(img,files,key,slice,text,iffilename,iffilesize,ifcount){ text=text||"" slice=slice||1 return wrap(files,slice) .then(array=>Promise.all(array.map((data,i)=>{ let texts=[text] if(iffilename){ texts.push(files[0].name+((files.length>1)?"等":"")) } if(iffilesize){ texts.push(sizec(data.length)) } if(ifcount){ texts.push((i+1)+"/"+array.length) } let img1=(img.length==0)?null:img[i%img.length] return picenc(img1,data,key,texts).then(uarr=>new Blob([uarr.buffer],{type:"image/png"})) }))) } </script> <script> document.getElementById("fail").appendChild(assembler.fdiv) document.getElementById("pending").appendChild(assembler.pdiv) document.getElementById("assembling").appendChild(assembler.adiv) document.getElementById("success").appendChild(assembler.div) document.getElementById("decode").onclick=()=>{ let keytext=document.getElementById("decodepassword").value tankcrypto.createkey(keytext) .then(key=>assembler.trydec(key)) .then(i=>document.getElementById("decodeinfo").innerText="成功解密"+i+"个") .catch(()=>{}) } document.getElementById("clear").onclick=()=>{ assembler.assembling={} assembler.pending=[] assembler.fail=[] assembler.div.innerHTML="" assembler.adiv.innerHTML="" assembler.pdiv.innerHTML="" assembler.fdiv.innerHTML="" assembler.srclist.map(x=>URL.revokeObjectURL(x)) assembler.srclist=[] } </script> <script> let FILES=[] let SRCS=[] let IMG=[] let ipt=document.createElement("input") ipt.type="file" ipt.multiple=true document.getElementById("encodeipt").appendChild(ipt) ipt.onchange=()=>{ FILES=Array.from(ipt.files) } document.getElementById("pack").onclick=()=>{ document.getElementById("display").innerHTML="" SRCS.map(x=>URL.revokeObjectURL(x)) SRCS=[] if(FILES.length==0){ alert("请先选择文件") return } document.getElementById("packinfo").style.display="inline" tankcrypto.createkey(document.getElementById("encodepassword").value) .then(key=>{ return make(IMG,FILES,key, parseInt(document.getElementById("slice").value), checklist[0].checked?document.getElementById("text").value:"", checklist[2].checked,checklist[3].checked,checklist[1].checked) }) .then(blobs=>blobs.map(b=>{ let src=URL.createObjectURL(b) SRCS.push(src) let imgbox=createimg(src) document.getElementById("display").appendChild(imgbox) })) .then(()=>{ document.getElementById("packinfo").style.display="none" }) } function createimg(src){ let img=document.createElement("img") img.style.maxWidth="100%" img.src=src return img } let ipt2=document.createElement("input") ipt2.type="file" ipt2.accept="image/png" ipt2.multiple=true document.getElementById("decodeipt").appendChild(ipt2) ipt2.onchange=()=>{ assembler.push(ipt2.files) } let ipt3=document.getElementById("ipt3") ipt3.onchange=()=>{ Promise.all(Array.from(ipt3.files).map(file=>new Promise((resolve,reject)=>{ let img=new Image() img.src=URL.createObjectURL(file) img.onload=()=>{ URL.revokeObjectURL(img.src) resolve(img) } }))).then(array=>{ IMG=array }) } </script> </body> </html> 提示:你可以先修改部分代码再运行。 转载请注明:有爱前端 » 图片化打包 喜欢 (0)or分享 (0)