文件上传
文件上传是项目开发中最常见的功能。为了能上传文件,必须将表单的method设置为POST,并将enctype设置为multipart/form-data。只有在这样的情况下,浏览器才会把用户选择的文件以二进制数据发送给服务器。
一旦设置了enctype为multipart/form-data,浏览器即会采用二进制流的方式来处理表单数据,而对于文件上传的处理则涉及在服务器端解析原始的HTTP响应。在2003年,Apache Software Foundation发布了开源的Commons FileUpload组件,其很快成为Servlet/JSP程序员上传文件的最佳选择。
下面是我项目中的一个事例:
1.js页面:
<div id="uploadQrCode">
<input type="file" accept="image/*" id="file" onchange="uploading()" style="display: none">
<div class="content">
<div class="immediately" onclick="x()">
立即上传
</div>
</div>
</div>
<script>
//选择文件
function x() {
document.getElementById("file").click();
}
function uploading() {
var formData = new FormData();
formData.append('file',$('#file')[0].files[0]);
formData.append('workID',$('#workID').val());
var fileSize =$('#file')[0].files[0].size;
var size = fileSize/1024;
if(size>1024){
$("#tishi").text("请上传不超过1M的文件!");
var test = document.getElementById('file');
test.outerHTML = test.outerHTML;
}else{
$.ajax({
url:'${pageContext.request.contextPath}/mobile/screenshotQR',
type:'post',
data:formData,
//必须false才会自动加上正确的Content-Type
contentType: false,
//必须false才会避开jQuery对 formdata 的默认处理
//XMLHttpRequest会对 formdata 进行正确的处理
processData: false,
cache:false,
success:function(data){
},
async:true
});
}
}
</script>
2.控制层
/**
* 文件上传(上传二维码)
*
* @param request
* @return
*/
@RequestMapping(value = "/screenshotQR", method = {RequestMethod.GET, RequestMethod.POST})
@ResponseBody
public String screenshotQR(HttpServletRequest request) {
try {
MultipartHttpServletRequest multipartRequest = (MultipartHttpServletRequest) request;
//file是form-data中二进制字段对应的name
MultipartFile multipartFile = multipartRequest.getFile("file");
InputStream inputStream = multipartFile.getInputStream();
//文件
String imgStr = ImageUtils.getImgStr(inputStream);
String workID = request.getParameter("workID");
int num = (int) ((Math.random() * 9 + 1) * 100000);
String nums = String.valueOf(num);
//将Base64位编码的图片(imgStr)进行解码,并保存到指定目录(/opt/wx_fx_8060/webapps/ROOT/static/wxQrCode/目录,workID + nums + ".png"是文件名字,ImageUtils是工具类)
Boolean boo = ImageUtils.decodeBase64ToImage(imgStr, "/opt/wx_fx_8060/webapps/ROOT/static/wxQrCode/", workID + nums + ".png");
if (boo) {
FenXiaoQrCodeDO fenXiaoQrCodeDOs = fenXiaoQrCodeMapper.queryInfoById(workID);
FenXiaoQrCodeDO fenXiaoQrCodeDO = new FenXiaoQrCodeDO();
//如果为空就创建,不为空就修改地址
if (fenXiaoQrCodeDOs == null) {
fenXiaoQrCodeDO.setWorkid(workID);
fenXiaoQrCodeDO.setWxqrurl("/static/wxQrCode/" + workID + nums + ".png");
fenXiaoQrCodeDO.setCreateTime(new Date());
fenXiaoQrCodeMapper.insertInfo(fenXiaoQrCodeDO);
} else {
//创建文件
File file = new File("/opt/wx_fx_8060/webapps/ROOT" + fenXiaoQrCodeDOs.getWxqrurl());
if (file.exists()) {
file.delete();
}
fenXiaoQrCodeDO.setWxqrurl("/static/wxQrCode/" + workID + nums + ".png");
fenXiaoQrCodeDO.setUpdateTime(new Date());
fenXiaoQrCodeMapper.updateInfoById(fenXiaoQrCodeDO);
}
return "文件上传成功!";
}
return "文件上传失败!";
} catch (Exception e) {
e.printStackTrace();
return "服务器出现异常,请稍后重试!";
}
}
注意提醒:这里ajax结合formdata对象上传文件是比较方便的如果对formdata不了解可以自行查看关于formdata的资料提供一个链接参考:https://developer.mozilla.org/zh-CN/docs/Web/API/FormData/Using_FormData_Objects
SpringMVC会将上传的文件绑定到MultipartFile对象中。MultipartFile提供了获取上传文件内容、文件名等方法。通过transferTo()方法还可以将文件存储到硬件中,MultipartFile对象中的常用方法如下:
1.byte[] getBytes():获取文件数据
2.String getContentType[]:获取文件MIME类型,如image/jpeg等
3.InputStream getInputStream():获取文件流
4.String getName():获取表单中文件组件的名字
5.String getOriginalFilename():获取上传文件的原名
6.Long getSize():获取文件的字节大小,单位为byte
7.boolean isEmpty():是否有上传文件
8.void transferTo(File dest):将上传文件保存到一个目录文件中
3.工具类ImageUtils
package io.bloom.insurance.web.util;
import org.apache.commons.codec.binary.Base64;
import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder;
import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.*;
import java.net.MalformedURLException;
import java.net.URL;
public class ImageUtils {
/**
* 将网络图片进行Base64位编码
*
* @param imgUrl 图片的url路径,如http://.....xx.jpg
* @return
*/
public static String encodeImgageToBase64(URL imageUrl) {// 将图片文件转化为字节数组字符串,并对其进行Base64编码处理
ByteArrayOutputStream outputStream = null;
try {
BufferedImage bufferedImage = ImageIO.read(imageUrl);
outputStream = new ByteArrayOutputStream();
ImageIO.write(bufferedImage, "jpg", outputStream);
} catch (MalformedURLException e1) {
e1.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
// 对字节数组Base64编码
BASE64Encoder encoder = new BASE64Encoder();
return encoder.encode(outputStream.toByteArray());// 返回Base64编码过的字节数组字符串
}
/**
* 将本地图片进行Base64位编码
*
* @param imgUrl 图片的url路径,如http://.....xx.jpg
* @return
*/
public static String encodeImgageToBase64(File imageFile) {// 将图片文件转化为字节数组字符串,并对其进行Base64编码处理
ByteArrayOutputStream outputStream = null;
try {
BufferedImage bufferedImage = ImageIO.read(imageFile);
outputStream = new ByteArrayOutputStream();
ImageIO.write(bufferedImage, "jpg", outputStream);
} catch (MalformedURLException e1) {
e1.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
// 对字节数组Base64编码
BASE64Encoder encoder = new BASE64Encoder();
return encoder.encode(outputStream.toByteArray());// 返回Base64编码过的字节数组字符串
}
/**
* 将Base64位编码的图片进行解码,并保存到指定目录
*
* @param base64 base64编码的图片信息
* @return
*/
public static boolean decodeBase64ToImage(String base64, String path,
String imgName) {
BASE64Decoder decoder = new BASE64Decoder();
try {
FileOutputStream write = new FileOutputStream(new File(path
+ imgName));
byte[] decoderBytes = decoder.decodeBuffer(base64);
write.write(decoderBytes);
write.close();
} catch (IOException e) {
e.printStackTrace();
return false;
}
return true;
}
/**
* 将图片文件转化为字节数组字符串,并对其进行Base64编码处理
*
* @param in
* @return
*/
public static String getImgStr(InputStream in) {
// 将图片文件转化为字节数组字符串,并对其进行Base64编码处理
byte[] data = null;
// 读取图片字节数组
try {
data = new byte[in.available()];
in.read(data);
in.close();
} catch (IOException e) {
e.printStackTrace();
}
return new String(Base64.encodeBase64(data));
}
/**
* 将图片文件转化为字节数组字符串,并对其进行Base64编码处理
*
* @param imgFilePath
* @return
*/
public static String GetImageStr(String imgFilePath) {
byte[] data = null;
// 读取图片字节数组
try {
InputStream in = new FileInputStream(imgFilePath);
data = new byte[in.available()];
in.read(data);
in.close();
} catch (IOException e) {
e.printStackTrace();
}
// 对字节数组Base64编码
BASE64Encoder encoder = new BASE64Encoder();
return encoder.encode(data);// 返回Base64编码过的字节数组字符串
}
/**
* 对字节数组字符串进行Base64解码并生成图片
*
* @param imgStr
* @param imgFilePath
* @return
*/
public static boolean GenerateImage(String imgStr, String imgFilePath) {
if (imgStr == null) // 图像数据为空
return false;
BASE64Decoder decoder = new BASE64Decoder();
try {
// Base64解码
byte[] bytes = decoder.decodeBuffer(imgStr);
for (int i = 0; i < bytes.length; ++i) {
if (bytes[i] < 0) {// 调整异常数据
bytes[i] += 256;
}
}
// 生成jpeg图片
OutputStream out = new FileOutputStream(imgFilePath);
out.write(bytes);
out.flush();
out.close();
return true;
} catch (Exception e) {
return false;
}
}
/**
* 删除单个文件
*
* @param fileName 要删除的文件的文件名
* @return 单个文件删除成功返回true,否则返回false
*/
public static boolean deleteFile(String fileName) {
File file = new File(fileName);
// 如果文件路径所对应的文件存在,并且是一个文件,则直接删除
if (file.exists() && file.isFile()) {
if (file.delete()) {
//System.out.println("删除单个文件" + fileName + "成功!");
return true;
} else {
System.out.println("删除单个文件" + fileName + "失败!");
return false;
}
} else {
System.out.println("删除单个文件失败:" + fileName + "不存在!");
return false;
}
}
}
4.上传后在本地看找到图片是否存在到此文件,上传完成!