原本的多文件上传功能在选择文件时,只能通过同一范围的鼠标框选或者ctrl/shift多选取选择文件,这样选择文件很不灵活,而且在确定之后如果漏选了文件,再次点击上传按钮时会清空表单里的文件信息,只能重复之前的操作去选文件再加上漏选的文件,十分不方便。
所以在大部分网站上选择图片上传都是可以累加的,就是在第一次选择完文件点击确定后,第二次再点击上传按钮选文件会自动跟第一次的接在一起,然后展示在界面上,方便用户单独进行删除。文章的主旨就是在不用插件的情况下实现这样的效果。
可多次添加多个文件,点击删除图标可进行文件的移除
该项目用的是django+js
,前端部分基本都差不多,废话不多说,直接上代码吧。
这里贴主要的代码,如有问题可评论或私信。
form表单
{% block main %}
......
{% endblock %}
{% block script %}
{% endblock %}
自定义上传的组件的样式fileUpload.css
文件
.choose-file-clip {position: absolute;clip: rect(0, 0, 0, 0);
}.choose-file {padding: 5px 20px;font-size: larger;background: #2ECA8B;border-radius: 4px;color: white;cursor: pointer;
}.upfile-list-mes {color: #00bfff;
}.icon-remove {cursor: pointer;color: #FD5373;font-size: medium;
}.file-name {/*color: #00bfff;*/color: #161C2D;font-size: medium;margin: 0;
}
最重要的部分,文件追加逻辑 fileUpload.js
var fileLists = [];
var fileNameList = []// 选择文件
$("#selectFile").on('change', function (event) {let _files = this.files;// console.log(_files)if (_files.length > 0) {_files = Array.from(_files); //将伪数组专为真数组修改for (let i = 0; i < _files.length; i++) {// 文件去重处理if (fileNameList.indexOf(_files[i].name) === -1) {console.log('not found-->' + _files[i].name)fileLists.push(_files[i]);fileNameList.push(_files[i].name)let html = "" + _files[i].name + sizeToStr(_files[i].size) + "
"$('.upfile-list-mes').append(html);}}}console.log(fileLists)
})function sizeToStr(size) {var data = "";if (size < 0.1 * 1024) { //如果小于0.1KB转化成Bdata = size.toFixed(2) + "B";} else if (size < 0.1 * 1024 * 1024) { //如果小于0.1MB转化成KBdata = (size / 1024).toFixed(2) + "KB";} else if (size < 0.1 * 1024 * 1024 * 1024) { //如果小于0.1GB转化成MBdata = (size / (1024 * 1024)).toFixed(2) + "MB";} else { //其他转化成GBdata = (size / (1024 * 1024 * 1024)).toFixed(2) + "GB";}var sizestr = data + "";var len = sizestr.indexOf("\.");var dec = sizestr.substr(len + 1, 2);if (dec === "00") { //当小数点后为00时 去掉小数部分return ' (' + sizestr.substring(0, len) + sizestr.substr(len + 3, 2) + ')';}return ' (' + sizestr + ')';
}// 删除文件
$(document).on('click', '.icon-remove', function (event) {let ind = $(this).parent().index();$(this).parent().remove();fileLists.splice(ind, 1);fileNameList.splice(ind, 1);console.log(fileLists)
});
下面是前端提交form表单数据(包含文件)到后台的js,也就是django模板加载的addDataStructure.js
// 导入上传附加的js
document.write('');function SubmitForm() {var submitbtn1 = document.getElementById("SubmitTop");var submitbtn2 = document.getElementById("SubmitBottom");var title = document.getElementById("id_title").value;var full_name = document.getElementById("id_full_name").value;var knowledge_category = document.getElementById("id_knowledge_category").value;var team = document.getElementById("id_team").value;console.log(title, full_name, knowledge_category, team)//确认必选项是否都已填if (title === '' || full_name === '' || knowledge_category === '' || team === '') {submitbtn2.disabled = false;submitbtn1.disabled = false;$.messager.alert("提示", 'Must input all items with * !', "warning");return false;}var formData = new FormData($("#dataStructureForm")[0]);if (fileLists.length > 0) {var fileSize = 0// 判断文件大小for (let i = 0; i < fileLists.length; i++) {fileSize += fileLists[i].sizeif (fileSize > 50 * 1024 * 1024) {console.log('file size:', sizeToStr(fileSize))$.messager.alert("提示", '所有文件大小不能超过50M!', "warning");return}}// 将文件添加到form表单中$(fileLists).each(function (i, e) {formData.append('uploadFile', e)})}submit(formData)
}function submit(formData) {var submitbtn1 = document.getElementById("SubmitTop");var submitbtn2 = document.getElementById("SubmitBottom");submitbtn2.disabled = true;submitbtn1.disabled = true;submitbtn1.value = "loading...";submitbtn2.value = "loading...";$.ajax({url: server_url + '/teams/add_data_structure/',method: 'POST',data: formData,dataType: "json",processData: false,contentType: false,cache: false,success: function (data) {console.log("data:" + data);console.log("data:" + data.res);if (data.status === 200) {$.messager.alert("提示", data.msg, "info");console.log("data:" + data.msg);window.setTimeout("window.location=server_url+'/teams/data_structure'", 500);return;}submitbtn2.disabled = false;submitbtn1.disabled = false;submitbtn1.value = "Submit";submitbtn2.value = "Submit";console.log(data)$.messager.alert("提示", data.msg, "info");},//请求失败,包含具体的错误信息error: function (data) {console.log(data.msg);}});
}
附上django后台处理上传文件的接口代码,仅供参考,这里用的是序列化器写的。
接口url
urlpatterns = [path('add_data_structure/', AddDataStructureView.as_view(), name='add_data_structure'),
]
视图函数view.py
class AddDataStructureView(APIView):def get(self, request):ds = DataStructure()knowledge_category = [i[1] for i in ds.CATEGORY_CHOICES]teams = [i[1] for i in ds.TEAM_CHOICES]context = {'add_knowledge_category': knowledge_category,'add_teams': teams,}return render(request, 'teams/data_structure/add_data_structure.html', context)@transaction.atomicdef post(self, request):# print(request.data)serializer = DataStructureSerializer(data=request.data)if serializer.is_valid():# serializer.ds = serializer.save()# handle filefiles_obj = request.FILES.getlist('uploadFile')if files_obj:handle_files(request, files_obj, ds, TeamFileSerializer)return api_success('信息保存成功!Data loading')return api_bad_request('表单数据输入有误,认证失败,数据无法保存!')def handle_files(request, files_obj, obj, FileSerializer):"""封装好的文件处理函数,更新和添加都可调用"""files = []for file_obj in files_obj:filename = file_obj.namesuffix = filename.rsplit(".", 1)[1]file_data = {'file': file_obj,'filename': filename,'suffix': suffix,}if request.method == 'PUT':# 1.本地文件删除obj_files = obj.attachments.all()for file in obj_files:file.file.delete()# 2.文件数据记录删除(先删除子表数据记录)obj_files.delete()fs = FileSerializer(data=file_data)if fs.is_valid():new_file = fs.save()new_file.content_object = objnew_file.save()files.append(fs.data.get('id'))if request.method == 'POST':obj.attachments.add(*files)if request.method == 'PUT':obj.attachments.set(files)
ok,至此,文件的多次累加上传功能完成,文件的编辑回显会在单独发文介绍,若是该文对你有帮助,还望可以点赞收藏加关注哦!3Q!