文章目录
前言
使用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 |