31 lines
2.0 KiB
JavaScript
31 lines
2.0 KiB
JavaScript
/* Shared direct multipart transport for customer originals/corrections and operator finals. */
|
|
window.dtfUpload = async (file, {api, prefix='/uploads', startPath=prefix, progress=()=>{}, scope='guest', resume=true}) => {
|
|
const samples=new Blob([file.slice(0,65536),file.slice(Math.max(0,file.size-65536))]);
|
|
const hash=Array.from(new Uint8Array(await crypto.subtle.digest('SHA-256',await samples.arrayBuffer())),b=>b.toString(16).padStart(2,'0')).join('');
|
|
const key='dtf-upload:'+JSON.stringify([scope,file.name,file.size,file.lastModified,hash]);
|
|
let id=resume?localStorage.getItem(key):null,state;
|
|
if(id){try{state=await api(prefix+'/'+id);}catch(error){if(![404,410].includes(error.status))throw error;id=null;}}
|
|
if(!id){state=await api(startPath,{name:file.name,size:file.size});id=state.id;if(resume)localStorage.setItem(key,id);}
|
|
async function waitForScan(){
|
|
for(let attempt=0;attempt<150;attempt++){
|
|
const checked=await api(prefix+'/'+id);
|
|
if(checked.scan_state==='clean')return id;
|
|
if(['rejected','error'].includes(checked.scan_state))throw new Error(checked.scan_reason||'Arquivo bloqueado pela verificação de segurança.');
|
|
progress('Verificando segurança de '+file.name+'…');
|
|
await new Promise(resolve=>setTimeout(resolve,1000));
|
|
}
|
|
throw new Error('Verificação de segurança pendente. Tente novamente para consultar o resultado.');
|
|
}
|
|
if(state.complete)return waitForScan();
|
|
const done=new Set(state.parts||[]),size=state.part_bytes;
|
|
for(let offset=0,part=1;offset<file.size;offset+=size,part++){
|
|
if(done.has(part))continue;
|
|
progress('Enviando '+file.name+' · parte '+part+'/'+Math.ceil(file.size/size));
|
|
const signed=await api(prefix+'/'+id+'/parts/'+part,{});
|
|
const response=await fetch(signed.url,{method:'PUT',body:file.slice(offset,offset+size)});
|
|
if(!response.ok)throw new Error('Upload interrompido. Tente novamente para retomar.');
|
|
}
|
|
await api(prefix+'/'+id+'/complete',{});
|
|
return waitForScan();
|
|
};
|