上传图片的功能想必并不是什么费劲的事儿了,但大多数童鞋都是在本机(也是tomcat/jboss服务器)实现上传,且没有考虑图片重命名(中文乱码)的问题。
这篇博客的上传图片是基于真实的项目,且采用了nginx图片服务器,Windows和Linux服务器均可使用。
Jsp页面:需要一个file控件,一个hidden控件(用于建立自定义分类文件夹)和一个button(上传按钮)。
<div>
<p class="ui-tips">上传头像会自动生成头像缩略图片,您也可以拖动大图的裁剪区域,调整缩图内容。</p>
<p class="ui-tips">支持JPG、GIF、PNG等图片格式 推荐尺寸:180*180像素</p>
<input type="file" οnchange="uploadCoursePoster();" id="fileCoursePoster"
style="display: none;" name="fileCoursePoster" />
<span id="errorCoursePoster" style="color: red; display: none;">请上传图片!</span>
<input type="button" οnclick="upLoad()" value="上传头像" class="btn btn-sm btn-normal">
<input type="hidden" id="imageType" name="imageType">
</div>
Js:需要引入ajaxfileupload这个js。
function upLoad(){
document.getElementById("imageType").value = "headPicture"; //图片分类,自定义类型,是海报还是个人头像
$("#fileCoursePoster").click();
}
function uploadCoursePoster() {
var imageType = document.getElementById("imageType").value;
var studentId=$("#studentId").val();
$.ajaxFileUpload({
url : "/itoo-jrkj-student-web/media/uploadImages",
secureuri : false,
data : {
"studentId" : studentId,
"imageType" : imageType
},
fileElementId : "fileCoursePoster",// 文件选择框的id属性
dataType : 'json',
success : function(data) {
$("#imgCoursePoster").attr(
"src",
"http://123.56.120.25:8888/apple/"
+ data);
$('#headPic').val(data);
alert("上传成功!");
},
error : function(XMLHttpRequest, textStatus, errorThrown) {
alert("上传失败!");
}
});
}
Controller:
// 上传个人头像--生成图片路径并将路径保存到数据库
@RequestMapping(value = "media/uploadImages", produces = "text/plain;charset=UTF-8")
@ResponseBody
public void uploadImages(HttpServletRequest request,
HttpServletResponse response) throws IllegalStateException,
IOException {
// 上传到指定的文件夹中,imageType为文件夹的名字
String imageType = request.getParameter("imageType").toString(); //文件夹名,便于图片分类
MultipartHttpServletRequest multipartRequest = (MultipartHttpServletRequest) request;
String fileName = "";//图片的名字
Calendar date = Calendar.getInstance(); //以图片类别+日期规划图片文件夹层级
SimpleDateFormat format1 = new SimpleDateFormat("yyyy");
SimpleDateFormat format2 = new SimpleDateFormat("MM");
SimpleDateFormat format3 = new SimpleDateFormat("dd");
String year = format1.format(date.getTime());
String month = format2.format(date.getTime());
String day = format3.format(date.getTime());
// 上传的图片存储的路径,格式如下:
//------------------要先将文件传入本机Jboss下的jboss3.1/bin文件夹中,因为File获得图片的绝对路径是自己定位到这儿了
String uploadServicePath = "";
String filePath="";
for (Iterator it = multipartRequest.getFileNames(); it.hasNext();) {
String key = (String) it.next();
MultipartFile mulfile = multipartRequest.getFile(key);
fileName = mulfile.getOriginalFilename(); //获取上传图片的文件名,以便得到其在jboss中的路径
//获取存在服务器下的图片的绝对路径
File getFilePath=new File(fileName);//要根据图片名字获取路径
filePath=getFilePath.getAbsolutePath();//获取Jboss服务器bin路径
File file = new File(filePath);
mulfile.transferTo(file);//保存
}
File imagefile = new File(filePath);
//TODO:创建ftp客户端 --读配置文件
FTPClient ftpClient = new FTPClient();
ftpClient.setControlEncoding("GBK");
String hostname = "xxx.xxx.xxx.xxx"; //FTP服务器主机ip
int port = 21;//FTP服务器端口,默认就是21
String username = "apple"; //FTP服务器用户名(可以有多个)
String password = "apple123";//FTP服务器密码
try {
//链接ftp服务器
ftpClient.connect(hostname, port);
//登录ftp
ftpClient.login(username, password);
int reply = ftpClient.getReplyCode(); //ftp服务状态码
System.out.println("reply返回码是:"+reply);
//如果reply返回230就算成功了,如果返回530密码用户名错误或当前用户无权限。
if (!FTPReply.isPositiveCompletion(reply)) {
ftpClient.disconnect();
return ;
}
ftpClient.setFileType(FTPClient.BINARY_FILE_TYPE);
// 保存图片的相对路径到阿里云服务器
fileName=UUID.randomUUID().toString()+".jpg";//自定义图片名,也能防止汉字的干扰
uploadServicePath ="uploadImage/" + imageType + "/" + year + "/"
+ month+day+"/"+fileName; //上传到服务器的路径
//在nginx上创建文件夹,一次只能创建一级,所以建多级要分多次
ftpClient.makeDirectory("uploadImage");//什么的都不写的情况下,默认在root目录下创建文件夹,此处在nginx/apple/uploadImage下,apple文件夹是用户名,创建用户时自动建好的
ftpClient.makeDirectory("uploadImage/"+imageType);
ftpClient.makeDirectory("uploadImage/"+imageType+ "/" + year);
ftpClient.makeDirectory("uploadImage/"+imageType+ "/" + year +"/"+month+day);
InputStream input = new FileInputStream(imagefile);
ftpClient.storeFile(uploadServicePath, input);//文件你若是不指定就会上传到root目录下
input.close();
ftpClient.logout();
} catch (SocketException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}finally
{
if (ftpClient.isConnected())
{
try
{
ftpClient.disconnect();
} catch (IOException ioe)
{
ioe.printStackTrace();
}
}
}
// 根据id更新个人信息
Student student = new Student();
String studentId = request.getParameter("studentId");
student = studentBean.findStudentById(studentId, dataBaseName);
student.setDataBaseName(dataBaseName);
student.setHeadPic(uploadServicePath);
if (!studentBean.updateHeadPicture(student)) {
uploadServicePath = "error";
}
System.out.println("realPath-------------" + uploadServicePath);
JacksonJsonUntil jacksonJsonUntil = new JacksonJsonUntil();
jacksonJsonUntil.beanToJson(response, uploadServicePath);
}
// 读取往期图片
@RequestMapping(value = "media/readImages", produces = "text/plain;charset=UTF-8")
public void readImage(HttpServletRequest request,
HttpServletResponse response) {
// 或:从服务器中的相对位置读取图片
// String imagesPath
// =request.getSession().getServletContext().getRealPath("/")+request.getParameter("imagesPath");
String imagesPath = request.getParameter("imagesPath");
System.out.println("imagesPath-------------------" + imagesPath);
try {
File file = new File(imagesPath);
if (file.exists()) {
DataOutputStream temps = new DataOutputStream(
response.getOutputStream());
DataInputStream in = new DataInputStream(new FileInputStream(
imagesPath));
byte[] b = new byte[2048];
while ((in.read(b)) != -1) {
temps.write(b);
temps.flush();
}
in.close();
temps.close();
}
} catch (Exception e) {
e.printStackTrace();
}
}
有一个问题,就是上传过程中,Eclipse中常会出现net.connention.timeout;FireBug中出现“图像损坏”这两个异常,但并不影响使用。怀疑是我把所有图片都改为了JPG类型~ 还没测试到底是不是。
解决思路:在Controller里判断一下,截取原图片名字的类型,即“.xxx”或“.xxxx”,如果不属于jpg/jpeg/png/gif四种类型就不许上传,符合的将其重命名后再加上它本来的图片类型后缀。