Initial commit
This commit is contained in:
104
resources/js/uploader.js
Normal file
104
resources/js/uploader.js
Normal file
@@ -0,0 +1,104 @@
|
||||
import {createIcons, icons} from "lucide";
|
||||
export const CHUNK_SIZE = 8192;
|
||||
export function FSUploader(){
|
||||
return {
|
||||
files: [],
|
||||
rawFiles: [],
|
||||
section: document.querySelector("meta[name='fs-section']")?.content ?? '',
|
||||
init( oldFiles ){
|
||||
this.$watch('files', () =>{
|
||||
this.$nextTick(() => window.refreshIcons(this.$el) )
|
||||
})
|
||||
},
|
||||
get isUploading(){
|
||||
return this.files.some(f => !f.done && !f.error);
|
||||
},
|
||||
get hasErrors(){
|
||||
return this.files.some(f => f.error);
|
||||
},
|
||||
get allUploaded(){
|
||||
return this.files.length === 0 || this.files.every(f => f.done);
|
||||
},
|
||||
async submitFile(e){
|
||||
const selected = Array.from(e.target.files);
|
||||
e.target.value = '';
|
||||
|
||||
for( const raw of selected ){
|
||||
const totalChunks = Math.ceil(raw.size / CHUNK_SIZE );
|
||||
const index = this.files.length;
|
||||
this.files.push({
|
||||
name: raw.name,
|
||||
progress: 0,
|
||||
currentChunk: 0,
|
||||
totalChunks: totalChunks,
|
||||
done: false,
|
||||
error: null,
|
||||
uuid: crypto.randomUUID()
|
||||
});
|
||||
this.rawFiles.push(raw);
|
||||
this.uploadChunks(raw,index);
|
||||
}
|
||||
},
|
||||
async uploadChunks(rawFile, index){
|
||||
const file = this.files[index];
|
||||
const url = `/api/fs/upload-chunk/${this.section}`;
|
||||
const csrf = document.querySelector('meta[name=csrf-token]')?.content ?? '';
|
||||
|
||||
for( let i = 0; i < file.totalChunks; i++ ){
|
||||
if( file.error )
|
||||
return;
|
||||
|
||||
const start = i * CHUNK_SIZE;
|
||||
const end = Math.min(start + CHUNK_SIZE, rawFile.size);
|
||||
const chunk = rawFile.slice(start, end);
|
||||
const formData = new FormData();
|
||||
|
||||
formData.append('file', chunk);
|
||||
formData.append('file_uuid', file.uuid);
|
||||
formData.append('current_chunk', i);
|
||||
formData.append('total_chunks', file.totalChunks);
|
||||
formData.append( 'filename', rawFile.name );
|
||||
formData.append('_token', csrf );
|
||||
|
||||
try {
|
||||
const response = await fetch(url, { method: 'POST', body: formData });
|
||||
if(!response.ok)
|
||||
throw new Error(`${response.status} ${response.statusText}`);
|
||||
|
||||
const data = await response.json();
|
||||
if( data.success !== true || data.uploaded !== true )
|
||||
throw new Error(`${data.error}`);
|
||||
|
||||
file.currentChunk = i + 1;
|
||||
file.progress = Math.round((( i + 1) / file.totalChunks ) * 100);
|
||||
|
||||
if( data.finished === true ){
|
||||
file.done = true;
|
||||
}
|
||||
} catch(err){
|
||||
file.error = 'Error on chunk ' + ( i + 1 ) + '. ' + err.message;
|
||||
file.progress = 0;
|
||||
return;
|
||||
}
|
||||
}
|
||||
},
|
||||
retry(index){
|
||||
const rawFile = this.rawFiles[index];
|
||||
const totalChunks = Math.ceil(rawFile.size / CHUNK_SIZE );
|
||||
this.files[index] = {
|
||||
name: rawFile.name,
|
||||
progress: 0,
|
||||
currentChunk: 0,
|
||||
totalChunks: totalChunks,
|
||||
done: false,
|
||||
error: null,
|
||||
uuid: crypto.randomUUID()
|
||||
};
|
||||
this.uploadChunks(raw,index);
|
||||
},
|
||||
remove(index){
|
||||
this.files.splice(index, 1);
|
||||
this.rawFiles.splice(index, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user