最近公司做的项目基本上都是用的前后端分离的架构进行的。在图片上传这块处理是先将图片上传到开发者服务器上,然后返回该图片在服务器上的图片地址存到数据库中。存到数据库的时候存的并不是网络地址,而是图片的相对路径,显示的时候再替换成服务器上的图片。刚开始不明白为何这么存,后来请教了公司的项目经理,项目经理说这样做,分布式部署的时候比较好。
服务端上传图片接口是基于rest形式的,代码如下:
@Path("upload")
@DenyAll
@POST
@Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.MULTIPART_FORM_DATA)
public Response uploadImage(@FormDataParam("imageFile")File fileInputStream,
@FormDataParam("imageFile")FormDataContentDisposition disposition,
@FormDataParam("subDir")String subDir){
try {
Map<String,Object> map = new HashMap<String,Object>();
String imgPath = "";
if(null != fileInputStream){
String fileFileName = disposition.getFileName();
//判断文件类型
String allowType = "gif,jpg,bmp,png,jpeg";
if(!("").equals(fileFileName.trim()) && fileFileName.length()>0){
String ex = (String) fileFileName.subSequence(fileFileName.lastIndexOf(".")+1,
fileFileName.length());
if(allowType.toString().indexOf(ex.toLowerCase())<0){
return Response.status(Response.Status.OK).entity(new RestResponse("1002","image type not allowed")).build();
}else{
String[] path = UploadUtil.upload(fileInputStream, fileFileName, subDir, 400, 400);
imgPath = path[0].replace(BusinessConstant.SOURCE_SERVER_DOMAIN, "fs:");
}
}
}
map.put("imgPath", imgPath);
return Response.status(Response.Status.OK).entity(new RestResponse(map)).build();
} catch (Exception e) {
logger.info("图片上传失败!", e);
return Response.status(Response.Status.OK).entity(new RestResponse(new HashMap())).build();
}
}
其中UploadUtil为图片上传工具类,开发者要在自己的项目中自己写上传的工具类。图片上传成功之后返回两个图片地址都是本地的。服务端图片处理基本上大同小异这里主要介绍下,前端调用接口的时候怎么调用。传统的前后端未分离的时候,前端主要是以form表单的形式提交上传图片,前台给input输入框一个name值,后端在action或者controller里定义一个和name值相同的变量,定义一个file对象即可获取到图片的二进制输入流。现在是前后端分离了,主要问题就是前端如何向后端服务器发送请求将图片的二进制输入流传给服务端。因为公司项目使用的是vue.js请求接口画页面,上传图片的时候把重心都放在了vue.js上了忽略了使用ajax的方法。后来上网查了资料在经过亲测发现还是单纯使用ajax发送请求好用,代码如下:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title></title>
<script type="text/javascript" src="js/jquery-1.9.1.min.js" ></script>
<script>
function upload(){
alert(111)
var file = document.getElementById("file").files[0];
}
$(function(){
$("#upload_image").click(function(){
var file = document.getElementById("file").files[0];
//var file = $("#file").files[0];
alert(file);
var data = new FormData();
data.append("imageFile",file);
$.ajax({
type:"post",
url:"http://192.168.0.102:8083/eoil/rest/my/upload",
contentType:"multipart/form-data",
data: data,
cache : false,
processData : false,
contentType : false,
type: 'POST',
timeout:3000,
beforeSend: function(request) {
request.setRequestHeader("Authorization", 'token');
},
success:function(result){
alert("添加成功");
},
error:function(result){
alert("添加失败!");
}
});
});
})
</script>
</head>
<body>
<form>
<input type="file" name="file" id="file"/>
<input type="button" id="upload_image" value="开始上传" />
<input type="text" name="username" id="un" value="123"/>
</form>
</body>
</html>
在前台通过document获取到文件上传的对象,这里我试了使用jquery的$("#").files[0]并不好用而且还报错,所以最好的方式还是通过原生js中的document来获取了,获取文件上传的对象之后将其封装在formdata对象中,这里要注意下放在formdata中对象的key值要和后台FormDataParam这个注解里的key值一样,这样就可以将图片的二进制文件传到服务端,服务端按照正常的图片上传就可以将图片上传到特定的文件下,并将地址url返回给客户端。这里说一下,使用这种形式上传图片一次只能上传一张图片。