2015-09-24 165 views
8

我实现阻力,在asp.net mvc的5, 滴状this文件但我的要求是,当我拖动文件,它不应该被立即上传。 首先拖动文件, 然后在一个按钮点击(“输入元数据”)进入一些强制性的属性(元数据的名称,类别&等)为每个文件, 然后点击其他按钮(提交)提交上传。拖,放和提交的文件上传

通常情况下,当我们拖动文件,它会立即被上传,我必须阻止它,做它按一下按钮(填充其他字段后)。即使任何具有类似功能的第三方js库?

我GOOGLE了很多,但没有得到预期的结果。 有人可以请指导我如何去这个要求或提供一些链接去这个要求。

回答

0

你试过Dropzone.js http://www.dropzonejs.com/ 看起来他们支持您正在寻找的功能。 以下摘录自相关页面。我没有自己尝试过,但纯粹基于文档,值得尝试检查它是否符合您的要求。

如果您禁用autoProcessQueue,则需要自行拨打 .processQueue()

如果要显示文件并让用户点击接受按钮以实际上传文件,这会很有用。

+0

是的,我有,但我们必须回答的基础上的问题:(这是一个非常不错的我使用过的库 –

+1

@AmirHosseinMehrvarzi如果我正确理解你的问题,我看到你要么回答说如何使用filedrop.js或者甚至是任何具有类似功能的第三方js库? 我的回答基本上是说,你使用dropzone.js而不是filedrop.js,看起来你已经使用它了。 如果你正在寻找一个解决方案“only”使用jquery-filedrop.js,请将你的问题改写为 – vvs

+0

@AmirHosseinMehrvarzi刚刚意识到OP是另一个人 OP或者想要一个答案说明如何去做使用filedrop.js或甚至任何具有类似功能的第三方js库?我的回答基本上是说,你使用dropzone.js而不是filedrop.js,因为它默认具有感兴趣的功能。看来你已经使用过它了,所以我认为你可以给答案增加一点颜色。 如果OP使用jquery-filedrop.js查找“唯一”解决方案,我建议重新说明问题。 – vvs

6

已链接到出现的示例代码是使用jquery.filedrop.js,这是由维西日元写的。您需要下载并使用其最新版本project home才能正常工作。

你也应该下载并使用jquery的版本比一个与示例代码捆绑在一起。我用jQuery 1.9.1测试了这个。

要使用您选择的jquery扩展,您需要利用beforeSend选项,并提供您自己的功能。您还需要存储对每个文件提供给自定义函数的done()函数的引用,以便以后可以调用它们,从而导致文件被上传。

如果你想元框来显示每个文件,那么你就需要追加对每个文件为基础的适当的HTML,让用户填写他们进来。

的代码我建议的总结如下:

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

类似于HTML如下:

​​

div#perfile应该有CSS来隐藏它,因为它只是用来包含DIV每次拖入文件时都要克隆到表单中。

我创建了一个概念证明jsfiddle here,显然这实际上并不允许文件上传,但它显示了JS方面的工作。您需要向下滚动到javascript面板的底部以查看自定义代码 - 顶部的内容仅包括您应该从项目主页下载的JavaScript扩展。

这确实应该足够好,你得到的东西工作asp.net侧。您只需以您认为合适的方式发布用户提供的其他元数据。

显然,这是准系统,你应该充实它,你认为合适。

+1

upcall会是什么? – coder771

2

根据我的研究,没有办法手动处理上传jquery.filedrop。您可以使用event functions像波纹管的一个prompt用户输入像元数据和一些等附加参数...,然后将它们连接到这样的发送数据:

$('#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

原谅我,如果我错了,这是不是我的答案相同? – enigma

+0

@enigma :)你已经扩展了存档库。但我使用事件来提示用户输入其他数据。是不是真的? –

+0

是的,你已经有了'prompt()'的链接。 [MDN链接](https://developer.mozilla.org/en-US/docs/Web/API/Window/prompt),如果任何人有兴趣。 – enigma

4

既然你正在寻找一个图书馆,我开发了一个完整的香草为您JavaScript的解决方案,具体如下:

/* 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>

上面的代码是完全注释,但如果你需要任何帮助,请留下评论。