文件上传(JavaScript实现)

设计思路:

form实现文件上传

内在也是通过form实现,

在Js中创建一个form 对象,点击按钮,触发事件(模拟form被点击),得到文件-》通过构造的form对象上传文件

前端代码:

<!DOCTYPE html>
<html>
	<head>
		<meta charset="UTF-8">
		<title></title>
		<script type="text/javascript" src="js/jquery.min.js" ></script>
		<script type="text/javascript" src="js/afquery.js" ></script>
		<style>
			.main{
				
			}
			
			.main input{
				margin: 20px;
			}
			.main .upload{
				background-color: cornflowerblue;
				color: #fff;
				border: 1px solid #ccc;
				border-radius: 1px;
				padding: 8px 18px;
			}
		</style>
	</head>
	<body>
		<div class="main">
			<input type="file" class="filebutton" style="display: none;" οnchange="fileSelected()" /><br />
			<button class="upload" οnclick="openFileDialog()">选择上传文件</button>
		</div>
	</body>
	
	<script>
		//点击普通按钮
		function openFileDialog()
		{
			//模拟鼠标点击事件
			$(".filebutton").click();
		}
		
		// 用户选择了一个文件 onchange事件被触发
		function fileSelected()
		{
			var fbutton = $(".filebutton")[0];  //DOM
			var file = fbutton.files[0];   //fbutton.files可能一次选择了多个文件
			fbutton.value = "";  //清空选择
			startUpload(file);   //开始上传
		}
		
		// 开始上传, 参数为 File 对象
		function startUpload( file )
		{
			var uploadUrl = "FileUploadService";
			
			// 手工构造一个 form 对象
			var formData = new FormData();
			formData.append('file', file); // 'file' 为HTTP Post里的字段名, file 对浏览器里的File对象
					
			// 手工构造一个请求对象,用这个对象来发送表单数据
			// 设置 progress, load, error, abort 4个事件处理器
		    var request = new XMLHttpRequest();		
		    request.upload.addEventListener("progress", window.evt_upload_progress, false);
		    request.addEventListener("load", window.evt_upload_complete, false);
		    request.addEventListener("error", window.evt_upload_failed, false);
		    request.addEventListener("abort", window.evt_upload_cancel, false);			
			request.open("POST", uploadUrl ); // 设置服务URL
		    request.send(formData);  // 发送表单数据
		}
		
		window.evt_upload_progress = function (evt) 
		{
		    if (evt.lengthComputable)
		    {
		    	var progress = Math.round(evt.loaded * 100 / evt.total);		    	
		    	Af.log ("上传进度: " + progress);		
		    }	        
		};
		window.evt_upload_complete = function (evt)
		{
			if(evt.loaded == 0)
			{
				Af.log ("上传失败!");
			}
			else
			{
				Af.log ("上传完成!");
		    	var response = JSON.parse(evt.target.responseText);
		   		Af.log (response);
			}			
		};		 
		window.evt_upload_failed = function (evt) 
		{			
			Af.log  ("上传出错"); 
		};
		window.evt_upload_cancel = function (evt) 
		{
			Af.log( "上传中止!");	
		};

		
	</script>
</html>

后端代码:

package my;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.UUID;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.fileupload.FileItemIterator;
import org.apache.commons.fileupload.FileItemStream;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
import org.apache.commons.fileupload.util.Streams;
import org.json.JSONObject;

/**
 * Servlet implementation class FileUploadService
 */
@WebServlet("/FileUploadService")
public class FileUploadService extends HttpServlet 
{
	
	//文件上传的临时目录
	File tmpDir;

	@Override
	public void init() throws ServletException
	{
		File webRoot = new File(getServletContext().getRealPath("/"));
		tmpDir = new File(webRoot, "upload");
		tmpDir.mkdirs();  //上传进来的文件存放在 WebRoot/upload/ 下
	}


	protected void doPost(HttpServletRequest request, HttpServletResponse response) 
										throws ServletException, IOException 
	{
		JSONObject jresp = new JSONObject();
		try
		{
			Object data = doUpload(request, response);
			jresp.put("error", 0);
			jresp.put("reason",  "OK");
			if(data != null)
				jresp.put("data", data);
			
		} catch (Exception e)
		{
			jresp.put("error", -1);
			jresp.put("reason", e.getMessage());
		}
		
		response.setCharacterEncoding("UTF-8");
		response.setContentType("text/plain");			
		PrintWriter out = response.getWriter();
		out.write(jresp.toString(2));
		out.close();
	}
	
	private Object doUpload(HttpServletRequest request, 
								HttpServletResponse response) throws Exception 
	{
		boolean isMultipart = ServletFileUpload.isMultipartContent(request);
		if(!isMultipart)
			throw new Exception("请求编码必须为:multipart/form-data!");
		
		request.setCharacterEncoding("utf-8");
		
		// ServletFileUpload : commons包里提供的工具类
		ServletFileUpload upload = new ServletFileUpload();
		AfFileUploadInfo info = new AfFileUploadInfo();
		
		FileItemIterator iter = upload.getItemIterator(request);
		while(iter.hasNext())
		{
			//表单域
			FileItemStream item = iter.next();
			String fieldName = item.getFieldName();
			InputStream fieldStream = item.openStream();
			if(item.isFormField())
			{
				// 普通表单域: 直接读取值
		    	// 指的是<input>,<select>,<textarea>输入控件的值, 字符串类型
				String fieldValue = Streams.asString(fieldStream, "utf-8");
				printLog("表单域:" + fieldName + "=" + fieldValue);	
			}
		    else 
		    {
		    	// 文件域, 指<file>控件的值,指文件的数据
		    	// 生成唯一的文件名
		    	info.realName = item.getName(); // 原始文件名
		    	info.suffix = fileSuffix(info.realName); // 后缀
		    	info.tmpFileName = createTmpFileName(info.suffix); // 服务器临时文件名
		    	info.tmpFile = new File(tmpDir, info.tmpFileName);
		    	info.fileSize = 0; // 文件大小			    	
		    	
		    	printLog("文件上传开始:" + info.realName + " >> " + info.tmpFile);
			        
		        // 从FieldStream读取数据, 保存到目标文件			        
		        info.tmpFile.getParentFile().mkdirs();		        
		        FileOutputStream fileStream = new FileOutputStream(info.tmpFile);
		        try{
		        	// 从请求里读取文件数据,保存到本地文件
		        	info.fileSize = copy(fieldStream, fileStream);
		        }finally{
		        	try{ fileStream.close();}catch(Exception e){}
		        	try{ fieldStream.close();}catch(Exception e){}
		        }
		        
		        printLog("文件上传完成:" + info.realName + ", 大小: " + info.fileSize);
		    }
		}
		return info.tmpFileName;
	}
	
	private long copy(InputStream in, OutputStream out) throws Exception
	{
		long count = 0;
		byte[] buf = new byte[8192];
		while(true)
		{
			int n = in.read(buf);
			if(n < 0)
				break;
			if(n == 0)
				continue;
			out.write(buf, 0, n);
			
			count +=n;
		}
		return count;
	}
	
	//////////////////////////////////////////////////
	
	private void printLog(String message)
	{
		System.out.println(message);
	}
	
	//生成唯一的ID 
	private String createUUID()
	{
		String s = UUID.randomUUID().toString();
		String s2 = s.substring(0,8)+s.substring(9,13)+s.substring(14,18)+s.substring(19,23)+s.substring(24); 
		return s2.toUpperCase();
	}
	
	// 得到一个保证不重复的临时文件名
	private String createTmpFileName(String suffix)
	{
		SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd-HHmmss");
		String datestr = sdf.format(new Date());
		String name = datestr + "-" + createUUID() + "." + suffix;
		return name;
	}
	
	// 得到文件的后缀名
	public String fileSuffix(String fileName)
	{
		int p = fileName.lastIndexOf('.');
		if(p >= 0)
		{
			return fileName.substring(p+1).toLowerCase();  //转换成小写
		}
		return "";
	}

}
package my;

import java.io.File;

public class AfFileUploadInfo
{
	public String realName;   //原始文件名
	public String suffix;   //后缀
	public String tmpFileName;  //服务器临时文件名
	public File tmpFile;
	public long fileSize;  //文件大小
}
发布了246 篇原创文章 · 获赞 22 · 访问量 4万+

猜你喜欢

转载自blog.csdn.net/gjs935219/article/details/103279612