一、前言
一般上傳文件,都是通過<input type="file" />標簽,然后選擇本地文件,再進行上傳。最近遇到一個需求,就是由JS創建好一個二進制文件,然后上傳到服務器。原理還是比較簡單的,就是通過js提供的blob創建一個數據流。然后生成一個文件實例。然后提交到后端。
二、服務器代碼
服務器代碼就沒有什么說的,就是普通的接收文件的springboot代碼片段。
1 package com.wunaozai.demo.uploadfile; 2 3 import java.io.File; 4 import java.util.Iterator; 5 import java.util.UUID; 6 7 import javax.servlet.http.HttpServletRequest; 8 9 import org.springframework.stereotype.Controller; 10 import org.springframework.web.bind.annotation.GetMapping; 11 import org.springframework.web.bind.annotation.PostMapping; 12 import org.springframework.web.bind.annotation.RequestMapping; 13 import org.springframework.web.bind.annotation.ResponseBody; 14 import org.springframework.web.multipart.MultipartFile; 15 import org.springframework.web.multipart.MultipartHttpServletRequest; 16 import org.springframework.web.multipart.commons.CommonsMultipartResolver; 17 18 @Controller 19 @RequestMapping(value="/test/") 20 public class UploadFileDemoController { 21 22 @GetMapping(value="web") 23 public String web() { 24 return "upload/web"; 25 } 26 27 @ResponseBody 28 @PostMapping(value="upload") 29 public String uploadFile(HttpServletRequest request) { 30 CommonsMultipartResolver resolver = 31 new CommonsMultipartResolver(request.getSession().getServletContext()); 32 if(!resolver.isMultipart(request)) { 33 return "err"; 34 } 35 MultipartHttpServletRequest multiRequest = (MultipartHttpServletRequest) request; 36 Iterator<String> it = multiRequest.getFileNames(); 37 while(it.hasNext()) { 38 try { 39 MultipartFile uploadfile = multiRequest.getFile(it.next()); 40 File newfile = new File("C:\\tmp\\", "cc.txt"); 41 uploadfile.transferTo(newfile); 42 } catch (Exception e) { 43 e.printStackTrace(); 44 } 45 } 46 return "ok."; 47 } 48 }
三、前端代碼
前端代碼,分成三種方式上傳文件,還有一種創建文件直接下載。
1. 是通過傳統input的file類型,選擇本地文件,然后上傳。
2. 是通過創建文本文件,然后上傳到服務器。
3. 是通過創建二進制流,然后上傳到服務器。
4. 是通過創建二進制流,然后通過a標簽,思想下載功能。
1 <!doctype html> 2 <html lang="zh"> 3 <head> 4 <meta charset="utf-8"> 5 <title>JS創建文件</title> 6 </head> 7 8 <body> 9 <p> 10 <input type="file" id="upfile"> 11 </p> 12 <p> 13 <input type="button" id="upJS" value="用原生JS上傳"> 14 </p> 15 <p> 16 <input type="button" id="createTxtAndUpload" value="JS創建txt文件並上傳"> 17 </p> 18 <p> 19 <input type="button" id="createBinAndUpload" value="JS創建bin文件並上傳"> 20 </p> 21 <p> 22 <input type="button" id="createBinAndDownload" value="JS創建bin文件並導出"> 23 </p> 24 <script> 25 /*原生JS版*/ 26 document.getElementById("upJS").onclick = function() { 27 /* FormData 是表單數據類 */ 28 var fd = new FormData(); 29 var ajax = new XMLHttpRequest(); 30 fd.append("upload", 1); 31 /* 把文件添加到表單里 */ 32 fd.append("upfile", document.getElementById("upfile").files[0]); 33 ajax.open("post", "/test/upload", true); 34 35 ajax.onload = function() { 36 console.log(ajax.responseText); 37 }; 38 ajax.send(fd); 39 } 40 document.getElementById('createTxtAndUpload').onclick = function() { 41 var file; 42 var data = []; 43 data.push("This is a test\n"); 44 data.push("Of creating a file\n"); 45 data.push("In a browser\n"); 46 var properties = {type: 'text/plain'}; // Specify the file's mime-type. 47 try { 48 // Specify the filename using the File constructor, but ... 49 file = new File(data, "file.txt", properties); 50 } catch (e) { 51 // ... fall back to the Blob constructor if that isn't supported. 52 file = new Blob(data, properties); 53 } 54 /* FormData 是表單數據類 */ 55 var fd = new FormData(); 56 var ajax = new XMLHttpRequest(); 57 /* 把文件添加到表單里 */ 58 fd.append("upfile", file); 59 ajax.open("post", "/test/upload", true); 60 61 ajax.onload = function() { 62 console.log(ajax.responseText); 63 }; 64 ajax.send(fd); 65 } 66 document.getElementById('createBinAndUpload').onclick = function() { 67 var data = str2ab("wunaozai"); 68 console.log(data); 69 var file = new Blob([data]); 70 /* FormData 是表單數據類 */ 71 var fd = new FormData(); 72 var ajax = new XMLHttpRequest(); 73 /* 把文件添加到表單里 */ 74 fd.append("upfile", file); 75 ajax.open("post", "/test/upload", true); 76 77 ajax.onload = function() { 78 console.log(ajax.responseText); 79 }; 80 ajax.send(fd); 81 } 82 document.getElementById('createBinAndDownload').onclick = function(){ 83 var data = str2ab("wunaozai"); 84 var file = new Blob([data]); 85 var aTag = document.createElement('a'); 86 aTag.download = "wunaozai.bin"; 87 aTag.style = "display: none"; 88 aTag.href = URL.createObjectURL(file); 89 document.body.appendChild(aTag); 90 aTag.click(); 91 setTimeout(function(){ 92 document.body.removeChild(aTag); 93 window.URL.revokeObjectURL(file); 94 }, 1000) 95 } 96 function str2ab(str){ 97 var array = []; 98 array.push(0x5a); 99 array.push(0xa5); 100 array.push(str.length); 101 for(var i=0; i<str.length; i++){ 102 array.push(str.charCodeAt(i)); 103 } 104 return new Uint8Array(array); 105 } 106 </script> 107 </body> 108 </html>
四、效果圖
如下圖,就是上傳到服務器上保存的文件,通過xxd工具查看二進制。可以看到有文件頭5AA5.
下面這個是前端界面
本篇只是做日常記錄。