第三部分:SpringMVC实现上传

1.1 思路

  (1)使用SpringMVC上传组件,从页面表单接收图片

  (2)使用vsftpd组件,将图片上传到Linux服务器

    a.服务端:在Linux上安装ftp服务端vsftpd软件,并开启服务。

    b.客户端:在java代码中使用FtpClient客户端建立与服务器的连接

  (3)返回值:返回图片上传之后的访问路径

    为什么?

    因为保存图片到数据库的时候,保存的就是图片的访问路径

1.2 前端js实现

调用上传组件的初始化方法:

上传组件在common.js中定义:

上传组件的初始化方法init

1.3 后台java实现

  1.3.1 代码结构

  • Controller:从表单接收图片,返回图片的回调地址
  • ·Service:创建FtpClient客户端,将图片直接上传到Linux服务器

  1.3.2 请求响应格式

请求路径

/pic/upload

请求方式

Post

请求参数

uploadFile

返回值结构

参考Kindeditor官方文档(http://kindeditor.net/docs/upload.html)

Kindeditor官方文档要求的返回格式类型:

  1.3.3 定义返回值类型

  在ego-base工程中定义。

package cn.gz.base.vo;

/**
 * kindeditor文件上传返回值类型
 * @author Administrator
 *
 */
public class UploadResult {

    private int error;    //标识    1表示失败    0表示成功

    private String url;    //上传成功时,文件的访问地址

    private String message;    //上传失败时,错误信息

    public int getError() {
        return error;
    }

    public void setError(int error) {
        this.error = error;
    }

    public String getUrl() {
        return url;
    }

    public void setUrl(String url) {
        this.url = url;
    }

    public String getMessage() {
        return message;
    }

    public void setMessage(String message) {
        this.message = message;
    }

    public UploadResult() {
        super();
    }

}

  1.3.4 在ego-manager工程中添加Springmvc上传组件及Pom依赖

  1.修改spring-mvc.xml,添加上传组件

<!-- 配置springmvc上传组件
     上传组件的name必须为multipartResolver
-->
<bean name="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
    <!-- 指定默认编码 -->
    <property name="defaultEncoding" value="utf-8"></property>
    <!-- 限制最大图片上传的大小 5mb 5*1024*1024 -->
    <property name="maxUploadSize" value="5242880"></property>
</bean>

  2.修改pom.xml,添加上传依赖common-fileupload.jar

<!-- 文件上传组件 -->
<dependency>
    <groupId>commons-net</groupId>
    <artifactId>commons-net</artifactId>
</dependency>

  3.在ego-bse工程下创建FtpUtil.java类

package cn.gz.base.utils;

import java.io.InputStream;

import org.apache.commons.net.ftp.FTP;
import org.apache.commons.net.ftp.FTPClient;

public class FtpUtil {

    /**文件上传
     * @param host     ftp主机地址
     * @param port      端口
     * @param username  ftp用户名
     * @param password  ftp用户密码
     * @param basePath  基础路径   /home/ftpuser/ego/images
     * @param filePath  文件的路径,按日期区分  /2019/04/26
     * @param remoteFileName   上传之后,文件的名称
     * @param local     待上传文件的流对象
     * @return
     */
    public static boolean upload(String host,Integer port,String username,String password,
            String basePath,String filePath,String remoteFileName,InputStream local){

        //1、创建ftp客户端
        FTPClient client = new FTPClient();
        try {

            //2、连接服务端
            client.connect(host, port);

            //3、登陆,认证身份
            boolean flag = client.login(username, password);

            if(flag){

                /*
                 * 切换上传的目录。
                 *
                 * 如果这个目录不存在,则切换失败
                 */
                boolean flag2 = client.changeWorkingDirectory(basePath+filePath);
                if(!flag2){
                    /*
                     * 如果目录不存在,则创建目录
                     *
                     * 注意事项:如果有多级目录的时候,必须一层一层目录去创建
                     */
                    String tempPath = basePath;

                    String[] paths = filePath.split("/");

                    for (String path : paths) {
                        if(null!=path && !"".equals(path)){
                            tempPath = tempPath +"/"+path;

                            //创建当前目录   tempPath= /home/ftpuser/ego/images/2019/04/26
                            /*
                             * 切换到目录不成功,则说明该目录不存在,要创建这个目录
                             *
                             * 如果切换成功,则继续循环,创建下一层目录
                             */
                            if(!client.changeWorkingDirectory(tempPath)){

                                //如果创建成功,则切换到该目录
                                if(client.makeDirectory(tempPath)){
                                    if(!client.changeWorkingDirectory(tempPath)){
                                        return false;
                                    }

                                }else{
                                    return false;
                                }

                            }else{
                                continue;
                            }

                        }else{
                            continue;
                        }    

                    }
                }

                //5、指定上传为被动上传   因为:很多的客户端禁止主动模式
                client.enterLocalPassiveMode();

                //6、指定上传方式为二进制,即使用字节流
                client.setFileType(FTP.BINARY_FILE_TYPE);

                //7、上传
                boolean result = client.storeFile(remoteFileName, local);

                return result;

            }else{

                return flag;
            }

        } catch (Exception e) {
            e.printStackTrace();

            return false;

        } finally {

            try {
                if(client.logout()){
                    client.disconnect();
                }
            } catch (Exception e) {

                e.printStackTrace();
            }

        }
    }

}

  4.将vsftpd服务端请求参数写到ego-manager工程里边的properties配置文件中

#配置ftp服务
FTP_HOST=192.xxx.xxx.24
FTP_PORT=21
FTP_USERNAME=ftpuser
FTP_PASSWORD=ftpuser
FTP_BASE_URL=/home/ftpuser/ego/images

PIC_BASE_URL=http://192.xxx.xxx.24/images

  1.3.5 Service层代码实现

  创建UploadService接口及其实现类

package cn.gz.manager.service;

import org.springframework.web.multipart.MultipartFile;

import cn.gz.base.vo.UploadResult;

public interface UploadService {

    /**
     * 实现文件上传
     * @param file    接收从页面表单发送的文件
     * @return
     */
    UploadResult upload(MultipartFile file);
}
package cn.gz.manager.service.impl;

import java.text.SimpleDateFormat;
import java.util.Date;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import cn.gz.base.utils.FtpUtil;
import cn.gz.base.vo.UploadResult;
import cn.gz.manager.service.UploadService;

@Service
public class UploadServiceImpl implements UploadService {

    /**
     * #配置ftp服务
FTP_HOST=192.168.232.24
FTP_PORT=21
FTP_USERNAME=ftpuser
FTP_PASSWORD=ftpuser
FTP_BASE_URL=/home/ftpuser/ego/images

PIC_BASE_URL=http://192.168.232.24/images
     */
    @Value("${FTP_HOST}")
    private String FTP_HOST;
    @Value("${FTP_PORT}")
    private Integer FTP_PORT;
    @Value("${FTP_USERNAME}")
    private String FTP_USERNAME;
    @Value("${FTP_PASSWORD}")
    private String FTP_PASSWORD;
    @Value("${FTP_BASE_URL}")
    private String FTP_BASE_URL;
    @Value("${PIC_BASE_URL}")
    private String PIC_BASE_URL;

    @Override
    public UploadResult upload(MultipartFile file) {

        UploadResult result = new UploadResult();

        try {
            //上传需求按日期划分图片的目录         /2019/04/26/1.jpg
            String filePath ="/"+ new SimpleDateFormat("yyyy").format(new Date())
                    +"/" + new SimpleDateFormat("MM").format(new Date())
                    +"/" + new SimpleDateFormat("dd").format(new Date());

            //获取文件的后缀,即格式
            String originalFilename = file.getOriginalFilename();
            //.jpg
            String fileType = originalFilename.substring(originalFilename.lastIndexOf("."));
            String remoteFileName = System.currentTimeMillis()+fileType;  //111.jpg

            boolean upload = FtpUtil.upload(FTP_HOST, FTP_PORT, FTP_USERNAME, FTP_PASSWORD, FTP_BASE_URL, filePath, remoteFileName, file.getInputStream());

            if(upload){
                result.setError(0);
                result.setUrl(PIC_BASE_URL+filePath+"/"+remoteFileName);
            }else{
                result.setError(1);
                result.setMessage("上传失败");
            }
         } catch (Exception e) {
            result.setError(1);
            result.setMessage(e.getMessage());
        }
        return result;
    }

}

  1.3.6 Controller层代码实现

  创建UploadController类

package cn.gz.manager.controller;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.multipart.MultipartFile;

import cn.gz.base.vo.UploadResult;
import cn.gz.manager.service.UploadService;

@Controller
public class UploadController {

    @Autowired
    private UploadService uploadService;

    @RequestMapping("/pic/upload")
    @ResponseBody
    public UploadResult upload(MultipartFile uploadFile){

        UploadResult result = uploadService.upload(uploadFile);
        return result;
    }
}

  1.3.7 测试结果,上传成功

1.4 将上传结果保存到页面表单域

页面效果

Vsftpd+Tengine+SpringMVC实现上传图片的更多相关文章

  1. springMVC中上传图片

    上传图片,很常见的问题,基本每个人都会遇到,但是个人认为在springMVC中上传图片相对来说是比较简单的,因为框架已经帮我们做好了许多事情. 这篇文章所用的环境:spring4.3.3 .jdk1. ...

  2. Maven+SpringMVC+MyBatis 上传图片

    上传文件我一直都觉得很难,好吧,所有涉及文件操作的我都觉得不容易.然后今天尝试了从网页上传图片保存到服务器.这个例子的前提是搭建好了服务器端框架:Maven+Spring MVC+MyBatis.当然 ...

  3. HTML5+Spring-MVC实现上传图片本地保存

    以下就是具体的代码: 1.在jsp页面中的代码: <span style="font-size:24px;"><form method="post&qu ...

  4. springmvc处理上传图片代码(校验图片尺寸、图片大小)

    package com.maizuo.web.controller; import com.maizuo.domain.Result; import com.maizuo.util.Constants ...

  5. springmvc异步上传图片并回调页面函数插入图片url代码示例

    <tr> <td class="search_td">属性值图片值:</td> <td> <input type=" ...

  6. SpringMVC+ajaxFileUpload上传图片 IE浏览器弹下载框问题解决方式

    如题,简单记录一下这个问题的解决的方法,导致问题的核心原因是:ajaxfileupload不支持响应头ContentType为application/json的设置.而且IE也不支持这样的格式,而当我 ...

  7. springmvc h5上传图片

    工作中开发一个评价功能,需要上传拍照的图片,后台使用springmvc接收文件,前端FormData异步提交. 1. spring配置multipartResolver <bean id=&qu ...

  8. SpringMVC上传图片总结(2)--- 使用百度webuploader上传组件进行上传图片

    SpringMVC上传图片总结(2)--- 使用百度webuploader上传组件进行上传图片   在上一篇文章中,我们介绍了< SpringMVC上传图片的常规上传方法 >.本文接着第一 ...

  9. SpringMVC框架之第四篇

    5.SpringMVC异常处理 5.1.异常分类 1.可预知异常: Java编译时可检测异常,例如:IOException.SQLException等. 自定义异常(继承Exception父类的自定义 ...

随机推荐

  1. Python序列结构--列表(一)

    列表 列表**包含若干元素的有序连续内存空间**,当列表增加或删除元素时,**列表对象自动进行内存的扩展或收缩**,从而**保证相邻元素之间没有缝隙**.但插入和删除非尾部元素时涉及列表元素大量的移动 ...

  2. 如何将已有的本地Git 库推送到远端仓库?

    以Github 为例 step 1. 在Github建立一个空的仓库 Step 2. 建立远端仓库的别名 >$ git remote add origin https://github.com/ ...

  3. .NET Core微服务之路:基于Consul最少集群实现服务的注册与发现(二)

    重温Consul最少化集群的搭建  

  4. Dev修改gridview 背景色

    private void gridView1_RowCellStyle(object sender, DevExpress.XtraGrid.Views.Grid.RowCellStyleEventA ...

  5. Akka-Cluster(3)- ClusterClient, 集群客户端

    上篇我们介绍了distributed pub/sub消息传递机制.这是在同一个集群内的消息共享机制:发布者(publisher)和订阅者(subscriber)都在同一个集群的节点上,所有节点上的Di ...

  6. [git] 本地仓库信息的查询

    本地仓库信息查询操作 1.1  git status 查看当前暂存区状态 git  status 显示当前分支信息: 提交的目的分支信息: git 管理的有修改的文件: 当前仓库未被 git 管理的文 ...

  7. python chr()和ord()的含义和使用方法

    通过help 查看相关函数的帮助文档 >>>help (chr) chr(...) chr(i) -> character Return a string of one cha ...

  8. linux下的shell脚本的使用

    什么是shell? Shell是一个命令解释器,它在操作系统的最外层,负责直接与用户进行对话,把用户的输入解释给操作系统,并处理各种各样的操作系统的输出结果,输出到屏幕反馈给用户.这种对话方式可是交互 ...

  9. 算法手记(2)Dijkstra双栈算术表达式求值算法

    这两天看到的内容是关于栈和队列,在栈的模块发现了Dijkstra双栈算术表达式求值算法,可以用来实现计算器类型的app. 编程语言系统一般都内置了对算术表达式的处理,但是他们是如何在内部实现的呢?为了 ...

  10. app自动化测试之实战应用(魅族计算器)

    模拟魅族计算器加法计算: from appium import webdriver desired_caps = {} desired_caps['deviceName'] = '621QECQ23D ...