H5移动端原生JS封装附件上传服务器

本文主要通过原生的js封装附件上传upload.js。可成功内嵌钉钉,ios和安卓端可正常使用,支持单个、多个附件上传。

一、业务需求

封装原生JS附件上传,动态创建附件列表,可对附件列表进行删除和新增功能。

二、业务逻辑

2.1 app.js 全局封装ajax请求,附件上传将文件流传递给后端,便于接收。

注:如果传递base64位字符串,字节长度解析可能导致服务器的端口过载或者文件太大抛异常。

2.2 原生js封装upload.js,适用于只读和非只读的两种情况下,后者可上传附件和编辑附件,前者只能查看和下载操作,对于新上传的附件,暂不支持预览等下载操作。单个附件控制不大于50M。

对于新上传的附件,暂不支持预览等下载操作说明:由于原生window.open直接打开base64位,会有默认的防钓鱼操作,实现上有安全性考虑。可通过上传服务器再返回,实现该附件下载或预览的统一操作,但会占用服务器资源,此处暂不支持。

2.3 代码的引入和调用
尽量可能做到js调用只用一行代码实现,增加便捷和可行性。

2.4 全局的基础样式美化
现在点击位置写好按钮的样式,图片效果最佳。通过将input type = file 设置绝对定位,宽高100%,上左定位为0,透明度为0,层级z-index在点击位置之上即可。建议层级比图片高一级即可。

三、实例代码

3.1 app.js

ajaxFile: function(option) {  // 通过formData的形式将附件的文件流请求发给后端
		ajaxCount++;
		var _ajaxCount = ajaxCount; 
		if (!option.error) {
			option.error = ajaxError;  
		}
		return $.ajax({
			type: option.type || "POST",
			url: app.getItem(app.localKey.url) + option.url,  // 自行配置URL
			timeout: option.timeout || 5 * 60 * 1000,
			dataType: "json",
			data: option.data,
			processData: false, // ajax不处理发送的数据
			contentType : false,
			success: function(r) {  // 返回值根据实际情况再做调整
				if (option.mustexe && option.validateUserInfo) {
					option.success && option.success(r);
				} else if (_ajaxCount == ajaxCount && option.validateUserInfo) {
					option.success && option.success(r);
				}
			},
			error: option.error
		});
	},
	attach: function(fileId, url) { // 附件下载
	var isDD = app.getItem(app.localKey.isDD) || app.otherLogin;  // 用户信息,下载校验
		var _url = app.serverUrl + "file.sp?act=fileDownload&loginUser=" + app.getItem(app.localKey.loginUser) +
			"&encAttachId=" + fileId + "&isDD=" + isDD;
		if (url) {
			_url = url;
		}
		window.open(_url);
	},

3.2 upload.js
以下方法调用了mui.js做弹窗提示组件,如需引入jq可以自行修改。

(function(doc, $, app) {
	window.upload = {
		isRead: false, // 默认false,附件是否只读,否可以上传附件,否可以删除附件
		uploadFiles: [], // 新附件
		oldFiles: [], // 旧附件
		onReady: function(isRead, obj) { // 附件列表初始化isRead 是否只读 obj为旧附件的对象
			upload.isRead = isRead;
			if(obj&& obj.length>0){ // 是否有数据传递
				upload.oldFiles = obj; // 新旧数组的操作
				upload._isShowFileTitle();
				for (var i = 0, e; i < obj.length; i++) {
					e = obj[i];
					upload._innerHTML(e.name, e.id);
				}
			}
			var uploadBtn = $("#uploadBtn")[0]; // 附件上传按钮
			if (upload.isRead) {
				if (uploadBtn) {
					uploadBtn.innerHTML = "";
				}
			} else {
				if (uploadBtn) {
					var newtd =
						'
' uploadBtn.innerHTML = newtd; } var input = $("#uploadfile")[0]; input.onchange = function() { readFile(this); } var readFile = function(obj) { for (var i = 0; i < obj.files.length; i++) { var path = obj.files[i], fileName = path.name; if (path.size < 1024 * 1024 * 50) { upload.uploadFiles.push(path); upload._innerHTML(path.name); } else { $.toast('单个附件大小不能超过50M'); } } input.value = ""; upload._isShowFileTitle(); } } }, _innerHTML(fileName, id) { // 附件列表动态输出 var ul = ul = $('#selectList')[0]; var newli = doc.createElement('li'); var img = upload._getIcon(fileName); newli.setAttribute("class", "mui-table-view-cell text-overflow"); newli.setAttribute("style", "height:44px;"); if (upload.isRead) { // 只读没有删除按钮 if (id) { newli.innerHTML = '
' + '
' + fileName + '
'; } else { newli.innerHTML = '
' + '
' + fileName + '
'; } } else { if (id) { newli.innerHTML = '
' + '
' + fileName + '
'; } else { newli.innerHTML = '
' + '
' + fileName + '
'; } } newli.setAttribute('fileName', fileName); ul.appendChild(newli); }, _getIcon(name) { // 附件图标 如果没有一一匹配的图表,请默认一个图片 var type = name.substr(name.lastIndexOf('.') + 1).toLowerCase(); //判断文件类型 var img = ""; if ('png' != type && 'doc' != type && 'jpg' != type && 'pdf' != type && 'rar' != type && 'txt' != type && 'wav' != type && 'xls' != type && 'zip' != type) { img = 'file-file.png'; } else { img = 'file-' + type + '.png'; } return img; }, _delElement(obj, filename) { // 删除附件 $.confirm('是否要删除该附件?', '*****', ['确定', '取消'], function(e) { if (e.index == 0) { var ul = obj.parentNode.parentNode; ul.removeChild(obj.parentNode); // 删除节点 for (var i = 0; i < upload.uploadFiles.length; i++) { var e = upload.uploadFiles[i]; if (e.name == filename) { upload.uploadFiles.splice(i, 1); upload._isShowFileTitle(); // 判断是否显示附件列表 $.toast('删除成功'); return; } } if (upload.oldFiles) { for (var i = 0; i < upload.oldFiles.length; i++) { var e = upload.oldFiles[i]; if (e.name == filename) { upload.oldFiles.splice(i, 1); upload._isShowFileTitle(); // 判断是否显示附件列表 // taskFeedbkEdit.updataFile(); // 获取就旧数组传值 $.toast('删除成功'); return; } } } } }); }, _isShowFileTitle() { // 添加页是否显示附加标题 && 编辑页判断数组是否为空 var appendix = $("#appendix")[0]; if (appendix) { if (upload.uploadFiles.length > 0 || upload.oldFiles.length > 0) { appendix.style.display = "block"; } else { appendix.style.display = "none"; } } else { var empty = doc.getElementById("empty"); if (upload.oldFiles.length == 0 && upload.uploadFiles.length == 0 && upload.isRead) { var ul = doc.getElementById("selectList"); ul.innerHTML = ""; var m = doc.createElement("li"); m.id = "empty"; m.setAttribute("class", "mui-table-view"); m.setAttribute("style", "background-color: #FFF;padding: 10px;margin-top: 0;"); m.innerHTML = "暂无附件。"; ul.appendChild(m); } } }, _getFormData(paramObj) { // 带附件的ajax请求 将参数转为formData的形式 var formData = new FormData(); if (paramObj) { for (var key in paramObj) { if (typeof paramObj[key] == "object" && paramObj[key].length) { var data = paramObj[key]; data.map(e => { formData.append(key, e); }) } else { formData.append(key, paramObj[key]) } } } // 用户标识 默认上传 var loginUser = app.getItem(app.localKey.loginUser), isDD = app.getItem(app.localKey.isDD) || app.otherLogin; var user = JSON.parse(localStorage.getItem("userInfo")); if (loginUser) { formData.append("loginUser", loginUser); } if (isDD) { formData.append("isDD", isDD); } return formData; }, } })(document, mui, app)

3.3 引入和调用
3.3.1 index.html 关键代码





    3.3.2 index.js 文件代码
    ① upload.js调用,附件初始化

    upload.onReady();  //附件初始化,附件删除
    
    upload.onReady(false, obj); // 附件初始化,不可编辑,旧附件显示
    
    upload.onReady(true, rfat); // 附件初始化,可编辑,旧附件显示
    

    ② ajax请求调用

    var data = {};
    for(var i = 0; i

    3.4 参考样式
    app.css

    .btn-upload{
    	opacity: 0;
    	position: absolute;
    	left: 0;
    	top: 0;
    	width: 100%;
    	height: 100%;
    	z-index: 10;
    }
    

    四、效果如下

    H5移动端原生JS封装附件上传服务器_第1张图片

    你可能感兴趣的:(前端小白)