浏览器 JavaScript 上传文件 笔记


前言

使用html的 form submit 会跳转

<form id="Form001" method="post" enctype="multipart/form-data" action="url">
	<input id="File001" type="file" name="file1" />
	<input type="submit"/>
</form>

于是探索新方法


直接发送files[0]

File是Bolb的继承, 可以用ajax直接发送

前端代码如下👇

<div id="Container"></div>
<script>
	const FileInput = document.createElement("input");
	FileInput.type="file"
	const Container = document.querySelector("#Container");
	Container.appendChild(FileInput);
	FileInput.onchange = function(){
		let file = FileInput.files[0]; if(file){
			let xhr=new XMLHttpRequest();
			xhr.open("post" , "/testFile");
			xhr.send(file);
		}
	};
</script>

后端代码如下👇

	@ResponseBody @RequestMapping("testFile")
	public void testFile(HttpServletRequest httpServletRequest) throws Exception{
		InputStream is = httpServletRequest.getInputStream();
		inputStreamDoSomething(is);
	}

用 FormData

FormData对象用以将数据编译成键值对,以便用XMLHttpRequest来发送数据。
其主要用于发送表单数据,但亦可用于发送带键数据(keyed data),而独立于表单使用。
如果表单enctype属性设为multipart/form-data ,则会使用表单的submit()方法来发送数据,从而,发送数据具有同样形式。

用 new FormData(formElement);

前端代码如下👇

<form id="用于测试FormData的Form" method="post" enctype="multipart/form-data">
	<input id="用于测试FormData的Form的FileInput" type="file" name="file1" />
</form><br/>
<script>
	const 用于测试FormData的Form =t= document.getElementById("用于测试FormData的Form");
	const 用于测试FormData的Form的FileInput =t= document.getElementById("用于测试FormData的Form的FileInput");
	t.onchange=function(){
		var file = 用于测试FormData的Form的FileInput.files[0];
		if(file){
			let formData = new FormData(用于测试FormData的Form);
			var xhr=new XMLHttpRequest(); xhr.open('post' , '/getParts');	xhr.send(formData); 
		}
	}
</script>

后端代码如下👇

	@ResponseBody @RequestMapping("getParts")
	public void getParts(HttpServletRequest request) throws Exception{
		System.out.println("Parts.size()="+request.getParts().size());
		for(Part part : request.getParts()) {
			if(part.getSize()>0) {
				String sar2d[][] = Excels.excelSheet0ToSar2d(part.getInputStream());
				pSar2d(sar2d);
			}
		}
	}

用 new FormData(); , FileInput来自form

前端代码如下👇 , 后端代码同上

<div id="Line1">
	<input id="FileOfFormData" type="file" name="file1" value="FileOfFormData" />
</div>
<script>
	const FileOfFormData =t= document.getElementById("FileOfFormData");
	t.onchange=function(){
		var file = FileOfFormData.files[0];
		if(file){
			let formData = new FormData();
			formData.append("这个名称不是文件名,是part名", file);
			var xhr=new XMLHttpRequest(); xhr.open('post' , '/getParts');
	// 		xhr.setRequestHeader("content-type","multipart/form-data");  不用设置这条, 设了反而报错
			xhr.send(formData);
		}
	}
</script>

用 new FormData(); , FileInput来自createElement()

前端代码如下👇 , 后端代码同上

<div id="Container"></div>
<script>
const 创建的FileOfFormData =t= document.createElement("input"); t.type="file";
document.getElementById("Container").appendChild(t);
t.onchange=function(){
	var file = 创建的FileOfFormData.files[0];
	if(file){
		let formData = new FormData();
		formData.append("这个名称不是文件名,是part名", file);
		var xhr=new XMLHttpRequest(); xhr.open('post' , '/getParts');
// 		xhr.setRequestHeader("content-type","multipart/form-data");  不用设置这条, 设了反而报错
		xhr.send(formData);
	}
}
</script>



用 FileReader

用 readAsArrayBuffer()

ArrayBuffer 保存字节数组

前端代码如下👇

<div id="Container"></div>
<script>
const File003 =t= document.createElement("input"); t.type="file" ; 
document.getElementById("Container").appendChild(t);
t.addEventListener("change", ()=>{
	let file = File003.files[0]; if(file){
		var fileReader = new FileReader(); fileReader.readAsArrayBuffer(file);
		fileReader.addEventListener("load", ()=>{
			let xhr = new XMLHttpRequest(); 
			xhr.open("post","/testArrayBuffer"); 
			xhr.send(fileReader.result);
		});
	}
});
</script>

后端代码如下👇

	@ResponseBody @RequestMapping("testArrayBuffer")
	public void testArrayBuffer(HttpServletRequest httpServletRequest) throws Exception{
		InputStream is = httpServletRequest.getInputStream();
		inputStreamDoSomething(is);
	}

用 readAsDataURL()

readAsDataURL 方法会读取指定的 Blob 或 File 对象。读取操作完成的时候,readyState 会变成已完成DONE,并触发 loadend (en-US) 事件,同时 result 属性将包含一个data:URL格式的字符串(base64编码)以表示所读取文件的内容。

前端代码如下👇:

<div id="Container"></div>
<script>
	const FileInput = document.createElement("input");
	FileInput.type="file"
	const Container = document.querySelector("#Container");
	Container.appendChild(FileInput);
	FileInput.onchange = function(){
		var file = FileInput.files[0];
		if(file){
			var fileReader = new FileReader();
			fileReader.readAsDataURL(file);
			fileReader.onload = function(){
				var result = fileReader.result;
				// readAsDataURL() 获得的base64前部有添加,内容在逗号之后
				var base64 = result.substring(result.indexOf(',')+1);
				var xhr = new XMLHttpRequest();
				xhr.open("post" , "/decodeBase64");
				xhr.send(base64);
			}
		}
		
	}
</script>

后端代码如下👇

	@ResponseBody @RequestMapping("decodeBase64")
	public void b64(@RequestBody String b64) {
		byte byteArray[] = Base64.getDecoder().decode(b64);
		userByteArrayDoSomething(byteArray);
	}



题外 : java中base64和base64URL的区别

        /**
         * This array is a lookup table that translates 6-bit positive integer
         * index values into their "Base64 Alphabet" equivalents as specified
         * in "Table 1: The Base64 Alphabet" of RFC 2045 (and RFC 4648).
         */
        private static final char[] toBase64 = {
            'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M',
            'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
            'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm',
            'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
            '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/'
        };

        /**
         * It's the lookup table for "URL and Filename safe Base64" as specified
         * in Table 2 of the RFC 4648, with the '+' and '/' changed to '-' and
         * '_'. This table is used when BASE64_URL is specified.
         */
        private static final char[] toBase64URL = {
            'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M',
            'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
            'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm',
            'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
            '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '-', '_'
        };

👆 可看出, +换成- , /换成_


Servlet的Part

方法描述返回值
write(String fileName)将文件内容写入指定的磁盘位置void
getSize()获取上传文件的大小long
getName()获取file控件的name属性String
getHeader(String name)获取指定请求头String
getHeaderNames()获取所有请求头的名称String
getHeaders(String name)获取指定header名称的集合数据Collection< String >
getContentType()获取文件MIME类型String
getInputStream()获取输入流用于检索文件的内容InputStream
delete()删除Part数据和临时目录数据,默认会删除void
getSubmittedFileName()获取上传文件名Servlet3.1 Tomcat8.0实现String
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

kfepiza

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值