当我们把base64图片上传到服务器时,您可能想到的是先将此文件作为base64图像字符串的形式传到服务器端,然后在服务器端将此其转换为一个图像文件,但是如果每个请求都这样做的话,无疑会极大的增加服务器端的工作。
因此在本文中,我们将学习如何将Base64字符串转换为Blob图像二进制的形式,然后使用jquery ajax异步上传到服务器中,此方法相当于用户做了一个Form表单提交了file文件输入框中的文件。
现在我们先开始将base64图片转换为图像文件Blob二进制流,使用javascript将base64图片转换为file文件的方式如下,该方法为自定义方法:
/** 参数一:base64字符串数据 参数二:base64文件类型 参数三:处理字符串大小 */ function b64toBlob(b64Data, contentType, sliceSize) { contentType = contentType || ''; sliceSize = sliceSize || 512; var byteCharacters = atob(b64Data); var byteArrays = []; for (var offset = 0; offset < byteCharacters.length; offset += sliceSize) { var slice = byteCharacters.slice(offset, offset + sliceSize); var byteNumbers = new Array(slice.length); for (var i = 0; i < slice.length; i++) { byteNumbers[i] = slice.charCodeAt(i); } var byteArray = new Uint8Array(byteNumbers); byteArrays.push(byteArray); } var blob = new Blob(byteArrays, {type: contentType}); return blob; }
我们使用一个Button按钮,使用Post异步请求提交Form表单,后面会有阻止Form表单直接提交的方法,之所以把Button放在<form>标签内部,后面会给出理由,代码如下:
<form id="myAwesomeForm" method="post" action="/php-code-that-handles-fileupload.php"> <!-- 可以输入一个文件名之后提交 --> <input type="text" id="filename" name="filename" /> <!-- Submit提交按钮 --> <input type="submit" id="submitButton" name="submitButton" /> </form>
下面是调用前面定义的b64toBlob()方法,将base64图片转化为图像文件的blob字节流,然后封装到javascript的FormData()对象中,并作为ajax的data数据提交到后台,代码如下:
// Get the form element withot jQuery var form = document.getElementById("myAwesomeForm"); //base64图片,由于数据过多,后面部分已经省略 var ImageURL = "data:image/gif;base64,R0lGODlhPQBEAPeoAJosM//AwO/AwHVYZ/z595kzAP/s7P+goOXMv8+fhw/v739/f+8PD98fH/8mJl+fn/9ZWb8/PzWlwv...."; // 切割base64字符串,获取图片类型与图片实体数据 var block = ImageURL.split(";"); // 获取图片类型 var contentType = block[0].split(":")[1];// 图像类型 "image/gif" // 获取base64图片内容实体 var realData = block[1].split(",")[1];// 图像数据实体部分 "R0lGODlhPQBEAPeoAJosM...." // 转化成blob字节流用于上传 var blob = b64toBlob(realData, contentType); // 创建FormData,将"image"作为后台的name参数,后台会用一个为"image" 的name变量来接收数据 var formDataToUpload = new FormData(form); //将blob添加到name属性 formDataToUpload.append("image", blob);
现在FormData中有了一个文件,我们可以使用jquery ajax来异步提交该文件了,代码如下:
//为什么上面的form表单中有了一个action="xxx"了,此处url还要输入一个网址呢?请稍后看最后面就明白!!! $.ajax({ url:"/php-code-that-handles-fileupload.php", data: formDataToUpload,// Add as Data the Previously create formData type:"POST", contentType:false, processData:false, cache:false, dataType:"json", // Change this according to your response from the server. error:function(err){ console.error(err); }, success:function(data){ console.log(data); }, complete:function(){ console.log("Request finished."); } });
完整的代码请看下方:
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>Base64 string to a file in form</title> </head> <body> <form id="myAwesomeForm" method="post" action="endpoint.php"> <input type="text" id="filename" name="filename" /> <!-- Filename --> <input type="submit" id="submitButton" name="submitButton" /> <!-- Submit --> </form> <script> function b64toBlob(b64Data, contentType, sliceSize) { contentType = contentType || ''; sliceSize = sliceSize || 512; var byteCharacters = atob(b64Data); var byteArrays = []; for (var offset = 0; offset < byteCharacters.length; offset += sliceSize) { var slice = byteCharacters.slice(offset, offset + sliceSize); var byteNumbers = new Array(slice.length); for (var i = 0; i < slice.length; i++) { byteNumbers[i] = slice.charCodeAt(i); } var byteArray = new Uint8Array(byteNumbers); byteArrays.push(byteArray); } var blob = new Blob(byteArrays, {type: contentType}); return blob; } $("#myAwesomeForm").submit(function(e){ //阻止Form表单直接被提交 e.preventDefault(); //然后使用ajax文件提交 appendFileAndSubmit(); }); function appendFileAndSubmit(){ // Get the form var form = document.getElementById("myAwesomeForm"); var ImageURL = "data:image/gif;base64,R0lGODlhPQBEAPeoAJosM//AwO/AwHVYZ/z595kzAP/s7P+goOXMv8+fhw/v739/f+8PD98fH/8mJl+fn/9ZWb8/PzWlwv...."; var block = ImageURL.split(";"); // Get the content type var contentType = block[0].split(":")[1];// In this case "image/gif" // get the real base64 content of the file var realData = block[1].split(",")[1];// In this case "R0lGODlhPQBEAPeoAJosM...." // Convert to blob var blob = b64toBlob(realData, contentType); // 创建FormData对象并添加一个file文件 var fd = new FormData(form); fd.append("image", blob); // Submit Form and upload file $.ajax({ url:"endpoint.php", //后台接收上传的文件 data: fd, //提交formData字节流的数据 type:"POST", contentType:false, processData:false, cache:false, dataType:"json", error:function(err){ console.error(err); }, success:function(data){ console.log(data); }, complete:function(){ console.log("Request finished."); } }); } </script> </body> </html>
下面来看php后台大概是如何接收的,如果是Java web项目大致也一样,就是使用(MultipartFile image)这个image属性来接收参数即可,先看看php后台服务器的大致写法吧!
<?php // Important to use these statemenets, the json response is optional for our response. use Symfony\Component\HttpFoundation\Request; public function retrieveAction(Request $request){ // retrieve the file with the name given in the form. // do var_dump($request->files->all()); if you need to know if the file is being uploaded. $file = $request->files->get('image'); $nameInTextInput = $request->request->get("filename"); }
说明:项目的语言等可能和你用的不一样,但是思想是一致的,就是将base64图片转换为图像文件,然后使用form表单提交或者ajax提交即可。