2015-09-24 20 views
8

Io sono l'attuazione drag and drop di file come this in asp.net mvc 5, ma la mia richiesta è quando mi trascino i file, non dovrebbe essere immediatamente caricato. trascinare il file, Quindi fare clic su un pulsante ("Enter metadati") per entrare poche proprietà obbligatorie (metadati-nome, categoria & ecc ...) per ogni file, Quindi fare clic sul pulsante altro (Submit) da inviare per caricare.Trascinare i file goccia e inviare per caricare

Normalmente quando trasciniamo un file, esso viene immediatamente caricato, devo fermarlo e farlo sul pulsante clic (dopo aver riempito gli altri campi). Anche una libreria js di terze parti con funzionalità simili?

Ho cercato su Google un sacco ma non ho ottenuto risultati attesi. Qualcuno può dirmi come andare per questo requisito o fornirmi dei collegamenti per questo requisito.

risposta

0

Hai provato Dropzone.js http://www.dropzonejs.com/ Sembra che abbiano il supporto per una funzione che stai cercando. Di seguito è estratto dalla pagina relativa. Non l'ho provato da solo, ma semplicemente basato sulla documentazione che vale la pena provare per verificare se soddisfa le tue esigenze.

Se avete autoProcessQueue disattivato, sarà necessario chiamare .processQueue() te stesso.

Questo può essere utile se si desidera visualizzare i file e lasciare che l'utente clicchi su un pulsante di accettazione per caricare effettivamente i file.

+0

Sì, ho, Ma dobbiamo rispondere in base alla domanda :(questo è molto bello libreria con cui ho lavorato –

+1

@AmirHosseinMehrvarzi Se ho compreso correttamente la tua domanda, sto vedendo che vuoi e rispondi che dice come farlo usando filedrop.js O anche qualsiasi libreria js di terze parti che abbia funzionalità simili? La mia risposta è stata sostanzialmente la seguente: tu usi dropzone.js invece di filedrop.js e sembra che tu abbia già lavorato con esso. Se stai cercando una soluzione "only" usando jquery-filedrop.js, ripeti la domanda a – vvs

+0

@AmirHosseinMehrvarzi Appena realizzato OP, un'altra persona: OP vuole una risposta che dice come farlo utilizzando filedrop.js O anche qualsiasi libreria js di terze parti che ha funzionalità simili? La mia risposta è stata fondamentalmente affermativa che si utilizza dropzone.js anziché filedrop.js in quanto ha la funzionalità di interesse disponibile per impostazione predefinita. Sembra che tu abbia già lavorato con esso, quindi penso che tu possa aggiungere un po 'di colore alla risposta. Nel caso in cui OP stia cercando una soluzione "only" usando jquery-filedrop.js, suggerisco di riformulare la domanda per dirlo. – vvs

6

Sembra che il codice di esempio a cui è stato collegato utilizzi jquery.filedrop.js, che è scritto da Weixi Yen. È necessario scaricare e utilizzare l'ultima versione dal suo project home affinché funzioni.

È inoltre necessario scaricare e utilizzare una versione successiva di jquery rispetto a quella in bundle con tale codice di esempio. Ho provato questo con jQuery 1.9.1.

Per utilizzare l'estensione jquery scelta, è necessario sfruttare l'opzione beforeSend e fornire la propria funzione. È inoltre necessario memorizzare i riferimenti alle funzioni done() fornite alla funzione personalizzata per ciascun file, in modo che sia possibile richiamarli in un secondo momento, causando il caricamento dei file.

Se si vuole meta scatole di apparire per ogni file, allora avete bisogno di aggiungere l'HTML appropriato in base al file per consentire all'utente di riempire loro in.

Una sintesi del codice che vorrei suggerire è qui di seguito:

var uploads_to_call = []; // the global to store all the file upload callbacks 

$('#dropzone').filedrop({ 
    fallback_id: 'upload_button', // an identifier of a standard file input element, becomes the target of "click" events on the dropzone 
    url: 'upload.php',    // upload handler, handles each file separately, can also be a function taking the file and returning a url 
    // other important parameters related to upload, read the documentation for details 

    // this is the important custom function you need to supply 
    beforeSend: function(file, i, done) { 
     // file is a file object 
     // i is the file index 
     // call done() to start the upload 

     // this is just to clone meta boxes for the user to fill in for each file 
     // it also fills in the filename so that it's obvious which meta boxes 
     // are for which files 
     $("#perfile").children().clone() 
      .appendTo("#allmeta") 
      .children(".filename").html(file.name); 

     // this pushes the done() callback into the global mentioned earlier 
     // so that we can call it later 
     uploads_to_call.push(done); 
    }, 
    afterAll: function() { 
     // runs after all files have been uploaded or otherwise dealt with 
     // you should possibly put code in here to clean up afterwards 
    } 
}); 

// set a handler to upload the files when the submit button is clicked 
$("#submit").click(function(){ 
    $.each(uploads_to_call, function(i, upcall) { 
     upcall(); 
    }); 
}); 

con l'HTML simile al seguente:

<form> 
    <div id="dropzone"></div> 
    <div id="allmeta"></div> 
    <button id="submit">submit</button> 
</form> 

<div id="perfile"> 
    <div class="meta"> 
     <span class="filename"></span> 
     <input type="text" placeholder="meta"/> 
     <input type="text" placeholder="meta"/> 
    </div> 
</div> 

il div#perfile dovrebbe avere CSS per nasconderlo, in quanto viene utilizzato solo per contenere il div da clonare nel modulo ogni volta che viene trascinato un file.

Ho creato un proof of concept jsfiddle here, ovviamente questo non consente effettivamente il caricamento dei file, ma mostra il lato JS delle cose che funzionano . È necessario scorrere verso il basso nella parte inferiore del pannello di JavaScript per visualizzare il codice personalizzato: le cose nella parte superiore includono solo l'estensione javascript che dovresti aver scaricato dal sito web del progetto.

Questo dovrebbe essere abbastanza buono per far funzionare il lato asp.net delle cose. Hai solo bisogno di pubblicare i metadati aggiuntivi forniti dall'utente nel modo che ritieni opportuno.

Ovviamente questo è barebone, dovresti incastrarlo come meglio credi.

+1

che cosa sarebbe in upcall? – coder771

2

Secondo la mia ricerca, Non c'è modo di gestire manualmente il caricamento in jquery.filedrop.È possibile utilizzare uno dei event functions come muggito per prompt all'utente di inserire alcuni parametri aggiuntivi come metadati ed ecc ... e poi attaccarle nei dati invio di questo tipo:

$('#myElement').fileDrop({ 
    data: { 
     param1: 'value1',   // send POST variables 
     param2: function(){ 
      return calculated_data; // calculate data at time of upload 
     }, 
    }, 
    onFileRead : function(fileCollection){ 
     $.each(fileCollection, function(){ 
      //Do stuff with fileCollection here! 
     }); 
    }, 
    drop: function() { 
     // user drops file 
    }, 
    beforeSend: function(file, i, done) { 
     // file is a file object 
     // i is the file index 
     // call done() to start the upload 
    }, 
    // Called before each upload is started 
    beforeEach: function(file){ 
     //do some stuff here 
    } 
}); 
+0

perdonami se sbaglio, non è la stessa cosa della mia risposta? – enigma

+0

@enigma :) hai esteso la libreria filedrop. Ma ho usato eventi per chiedere all'utente di inserire dati aggiuntivi. Non è vero? –

+0

true, hai il link per 'prompt()'. [Collegamento MDN] (https://developer.mozilla.org/en-US/docs/Web/API/Window/prompt), se qualcuno è interessato. – enigma

4

Dal momento che siete in cerca di una libreria, ho sviluppato una vaniglia piena Javascript soluzione per voi, come segue:

/* as soon as all the elements of the page has been loaded */ 
 
document.addEventListener('DOMContentLoaded', function() { 
 
    /* we reference the most used elements into variables, making it easier to use later */ 
 
    var dropzone = document.getElementById('dropzone'), 
 
     dialog = document.getElementById('dropzone-dialog'), 
 
     submit = document.getElementById('submit'), 
 
     progress = document.querySelector('progress'), 
 
     _current = null; // we keep track what file the user is changing its metadata 
 

 
    /* when the user drags something over our div, we must prevent the browser's default 
 
    behavior and we change a CSS class only for usability reasons */ 
 
    dropzone.addEventListener('dragover', function(e) { 
 
    e.preventDefault(); 
 
    dropzone.classList.add('dragging'); 
 
    }); 
 

 
    /* when the user leaves our div, we must remove the CSS class we put before */ 
 
    dropzone.addEventListener('dragleave', function(e) { 
 
    e.preventDefault(); 
 
    dropzone.classList.remove('dragging'); 
 
    }); 
 

 
    /* that's the heart of our code, 
 
    when the user effectively drops one or more files into the div */ 
 
    dropzone.addEventListener('drop', function(e) { 
 
    /* again we must prevent the default browser's behavior, 
 
     and we need to remove the CSS clas we put before */ 
 
    e.preventDefault(); 
 
    dropzone.classList.remove('dragging'); 
 
    submit.classList.add('hidden'); 
 

 
    /* we change our div's text */ 
 
    dropzone.textContent = 'File(s) dropped:'; 
 

 
    /* we create an UL element, so we can loop through the files make a list */ 
 
    var ul = document.createElement('ul'); 
 
    /* since the files property is not an array, but it is Array-like, 
 
     we call the Array.prototype.forEach method passing the files to be the context */ 
 
    [].forEach.call(e.dataTransfer.files, function(file) { 
 
     /* for each file the user has dropped, we create a LI and an anchor inside it */ 
 
     var li = document.createElement('li'); 
 
     var a = document.createElement('a'); 
 

 
     a.href = '#'; 
 
     a.textContent = file.name; 
 
     a.title = 'Enter metadata'; 
 
     
 
     /* we create a property __file into our anchor to reference the dropped file */ 
 
     a.__file = file; 
 

 
     li.appendChild(a); 
 
     ul.appendChild(li); 
 
    }); 
 
    dropzone.appendChild(ul); 
 
    }); 
 

 
    /* here, we add a 'click' event handler to our div dropzone, 
 
    so we can add the file's metadata behavior. 
 
    the idea here is to make an event delegation, that is, when the user clicks anywhere 
 
    inside the div, we see if the element that was clicked is one of the files */ 
 
    dropzone.addEventListener('click', function(e) { 
 
    var el = e.target; 
 

 
    /* if the element clicked is an anchor, it's because it's one of the files */ 
 
    if (el.tagName === 'A') { 
 
     /* we prevent the browser's default behavior */ 
 
     e.preventDefault(); 
 
     /* we keep track that the current clicked file/anchor is the last clicked */ 
 
     _current = el; 
 
     
 
     /* and then, we show our dialog, so the user can input the file's metadata */ 
 
     dialog.classList.remove('hidden'); 
 
     /* we set focus on the first element of the dialog, only for usability reasons */ 
 
     dialog.querySelector('#name').focus(); 
 
     
 
    } 
 
    }); 
 

 
    /* we add an event handler to the dialog's close button, 
 
    so it can effectively close the dialog */ 
 
    dialog.querySelector('.close').addEventListener('click', clearDialog); 
 
    
 
    /* this is the second heart of our code. 
 
    we add an event handler to the dialog's save button, 
 
    so it can handle the saving of metadata */ 
 
    dialog.querySelector('#save').addEventListener('click', function() { 
 
    /* here you can add any validation you want, e.g: required fields, etc */ 
 
    
 
    /* if everything was cool, we set a new property __dataFile to our anchor 
 
     so, we can save the metadata for future use (the form submission) */ 
 
    _current.__dataFile = { 
 
     name: dialog.querySelector('#name').value, 
 
     category: dialog.querySelector('#category').value 
 
     /* put here any other metadata property you will save */ 
 
    }; 
 
    
 
    /* when the user saves the metadata, we add a CSS class only for usability reasons */ 
 
    _current.classList.add('finished'); 
 

 
    /* then, we keep track if there is any file with no metadata saved yet */ 
 
    var btnsLeft = [].filter.call(dropzone.querySelectorAll('a'), function(el, i) { 
 
     return !('__dataFile' in el); 
 
    }); 
 

 
    /* if all the files' metadatas have been saved, we show the submit button */ 
 
    if (btnsLeft.length === 0) 
 
     submit.classList.remove('hidden'); 
 

 
    /* and we clear/close our dialog */ 
 
    clearDialog(); 
 
    }); 
 

 
    function clearDialog() { 
 
    /* when the dialog is closed, we set our current-clicked anchor to null */ 
 
    _current = null; 
 

 
    /* we clean all the input fields of the dialog */ 
 
    [].forEach.call(dialog.querySelectorAll('input'), function(el, i) { 
 
     el.value = ''; 
 
    }); 
 

 
    /* and we effectively hide/close the dialog */ 
 
    dialog.classList.add('hidden'); 
 
    } 
 

 
    /* this is third heart of our code. 
 
    we add a click event handler to our submit button, 
 
    so we can effectively send our form to the server */ 
 
    submit.querySelector('button').addEventListener('click', function(e) { 
 
    e.preventDefault(); // we must prevent the browser's default behavior 
 

 
    /* we create a XMLHttpRequest to send our AJAX to the server */ 
 
    var xhr = new XMLHttpRequest(); 
 

 
    /* we add a 'load' event handler, so we can keep track when the upload is finished */ 
 
    xhr.addEventListener('load', finished); 
 
    /* we do the same for progress and error, so we can inform our user what's going on */ 
 
    xhr.upload.addEventListener('progress', progress); 
 
    xhr.addEventListener('error', error); 
 
    
 
    /* now it's time to save all our data, so we create a FormData */ 
 
    var fd = new FormData(); 
 

 
    /* and for each anchor(file) inside our dropzone, we add new data to our FormData */ 
 
    [].forEach.call(dropzone.querySelectorAll('a'), function(el, i) { 
 
     /* here we loop through our __dataFile previously created property, 
 
     so we can add the file's metadata parameter */ 
 
     for (var prop in el.__dataFile) { 
 
     /* since we are sending multiple files/metadatas, 
 
      it's important to name our field with [] */ 
 
     fd.append(prop + '[]', el.__dataFile[prop]); 
 
     } 
 
     
 
     /* and then, we append the file itself - again, with the [] at the end */ 
 
     fd.append('file[]', e.__file); 
 
    }); 
 

 
    /* now we open the xhr, and we effectively send the request to the server */ 
 
    xhr.open('POST', '/api/uploadfiles/'); // change for your API URL 
 
    xhr.send(fd); 
 
    }); 
 
    
 
    /* this is the xhr's progress, so we can update our HTMLProgressElement's percent */ 
 
    function progress(e) { 
 
    progress.value = progress.innerHTML = (e.loaded/e.total * 100 | 0); 
 
    } 
 

 
    /* this is the xhr's finished event handler, 
 
    we show a friendly message and hide the submit button */ 
 
    function finished(e) { 
 
    progress.value = progress.innerHTML = 100; 
 
    dropzone.innerHTML = '<h3>Files successfully uploaded</h3>'; 
 
    submit.classList.add('hidden'); 
 
    } 
 
    
 
    /* this is the xhr's error event handler. If there is any known error, we show it */ 
 
    function error(e) { 
 
    var xhr = e.target; 
 
    submit.classList.add('hidden'); 
 
    dropzone.innerHTML = '<h3>Error while uploading</h3>' + 
 
     (xhr.status ? '<span>' + xhr.status + ' - ' + xhr.statusText + '</span>' : ''); 
 
    } 
 
});
#dropzone { 
 
    width: 450px; 
 
    height: 165px; 
 
    background-color: #CCC; 
 
    font: 16px Verdana; 
 
    padding: 10px; 
 
    box-sizing: border-box; 
 
} 
 
#dropzone.dragging { 
 
    background-color: #EEE; 
 
} 
 
#dropzone > h3 { 
 
    text-align: center; 
 
} 
 
#dropzone a { 
 
    text-decoration: none; 
 
} 
 
#dropzone a:hover { 
 
    text-decoration: underline; 
 
} 
 
#dropzone a.finished:after { 
 
    content: ' √'; 
 
    color: green; 
 
    font-weight: bold; 
 
    text-decoration: none; 
 
} 
 
#dropzone ul { 
 
    list-style: none; 
 
    margin-left: 15px; 
 
    padding: 0; 
 
} 
 
#dropzone li { 
 
    margin-top: 8px; 
 
} 
 
#dropzone li:before { 
 
    content: '> '; 
 
} 
 
.hidden { 
 
    display: none; 
 
} 
 
.dialog { 
 
    background-color: #AAAAFF; 
 
    font-family: Verdana; 
 
    padding: 12px; 
 
    border-radius: 10px; 
 
    width: 300px; 
 
    height: 150px; 
 
    position: absolute; 
 
    top: 20px; 
 
} 
 
.dialog h3 { 
 
    text-align: center; 
 
} 
 
.dialog .close { 
 
    text-decoration: none; 
 
    float: right; 
 
} 
 
.dialog .close:after { 
 
    content: '✖'; 
 
    cursor: pointer; 
 
} 
 
.dialog > div { 
 
    display: table; 
 
} 
 
.dialog > div > div { 
 
    display: table-row; 
 
} 
 
.dialog > div > div > div, 
 
.dialog > div > div > label { 
 
    display: table-cell; 
 
    padding: 2px 0 2px 10px; 
 
} 
 

 
#submit { 
 
    height: 160px; 
 
    width: 450px; 
 
    text-align: right; 
 
    position: fixed; 
 
    top: 10px; 
 
} 
 
#submit button { 
 
    font-size: 20px; 
 
    padding: 10px; 
 
    background-color: orange; 
 
} 
 

 
progress { 
 
width: 450px; 
 
}
<div id="dropzone"> 
 
    <h3>Drop your files here</h3> 
 
</div> 
 
<div> 
 
    <progress min="0" max="100" value="0"></progress> 
 
</div> 
 
<div id="submit" class="hidden"> 
 
    <button>Submit</button> 
 
</div> 
 
<div id="dropzone-dialog" class="dialog hidden"> 
 
    <a class="close"></a> 
 
    <h3>File Metadata</h3> 
 
    <div> 
 
    <div> 
 
     <label for="name"> 
 
     Name 
 
     </label> 
 
     <div> 
 
     <input id="name"> 
 
     </div> 
 
    </div> 
 
    <div> 
 
     <label for="category"> 
 
     Category 
 
     </label> 
 
     <div> 
 
     <input id="category"> 
 
     </div> 
 
    </div> 
 
    <div> 
 
     <div></div> 
 
     <div style="text-align: right"> 
 
     <button id="save">Save</button> 
 
     </div> 
 
    </div> 
 
    </div> 
 
</div>

Il codice di cui sopra è completamente commentato, ma se hai bisogno di aiuto, per favore lascia un commento.