上传图片文件至FTP服务器Ajax multipart formData FTP

最近在公司接手一个图片上传的功能实现,但需要上传保存在FTP服务器长久保存。解决Tomcat下保存,重启就会清空了的问题。既然是做测试,就在自己电脑搭建一个FTP服务器就好。FTP服务器如何在个人笔记本电脑搭建后续介绍,今天先来看这个功能代码如何写。

提交上传图片,同时还有两个其他数据需要提交

1. html页面

<html>
<head>
</head>
<body>
  <form id="form_fj" enctype="multipart/form-data">
        <div><!--此处上传一个id值 -->
            <input type="text" id="hidden_jtbm"/>
        </div> 
        <div id="divselect"> <!-- 该下拉框可以选择两种类型照片上传,根据数据库表业务逻辑来的,不必深究-->
        选择身份
            <select id="select_fj">
              <option value ="1">小哥哥照片</option>
              <option value ="2">小姐姐照片</option> 
            </select>
        </div>
        <div id="filePicker" class="uploader-list"><!--选择需要上传的图片 -->
            <input type="file" id="zjfile" name="zjfj" multiple="multiple"/>
        </div>
        <div><input type="button" value="上传" id="doUpload" /></div> 
  <form>
</body>
</html>

注意:form表单需标明enctype=”multipart/form-data”
input输入框type属性写为file

2. js代码

// 附件上传函数
$(function(){
    $("#doUpload").on('click',function(event){

    var formData = new FormData();
    var jtbm = $("#hidden_jtbm").val();
    var zjlx = $("#select_fj").val();
    <!--此部分若不懂,往下看解释-->
    formData.append("jtbm",jtbm);
    formData.append("zjlx",zjlx);
    formData.append("file",$("#zjfile")[0].files[0]);

    $.ajax({
        url : rootUri + 'up/fjUpload.json',//你自己的url地址
        type : 'post',
        data : formData,
        cache : false,
        processData : false,
        contentType : false,
        async : false,
        success : function(d) {
                alert("上传成功");
            } 
          })
    })
})

注意:1.遇到表单中图片需要跟表单一起提交,这样会造成后台没办法接收到图片。因为表单提交时是默认application/x-www-form-urlencoded格式,只接受键值对。所以我们采用FormData格式异步提交表单,因为formData格式可以接收文件格式。
2.创建一个formData对象并向其中添加键值对,这个值可以是一个文件。("#zjfile")[0]是取出id=zjfile的元素,至于为什么是[0],这是因为jquery对象都有一个默认为0的索引用来取出其Dom元素*,*** ("#zjfile")[0]是取出id=zjfile的元素,至于为什么是[0],这是因为jquery对象都有一个默认为0的索引用来取出其Dom元素*,*** (‘formData’)是一个jquery对象,[0]为Dom元素 可以用dom的所有属性和方法**。然后使用files来取出文件。这里我使用了files[0]还可以继续写files[1]等等,可以实现上传多个文件,我这里只上传了一个。然后服务器就可以接收文件了,和表单一样的接收方法。
3.
- cache : false,因为上传文件不需要缓存
- processData : false,因为data值是FormData对象,不需要对数据做处理。
- contentType设置为false。因为是由表单构造的FormData对象,且已经声明了属性enctype=”multipart/form-data”,所以这里设置为false。

3.Controller代码

/**
     * 上传图片文件方法
     * @param m 包含附件路径的Model类
     * @param file 文件
     * @param request
     * @return
     */
    @RequestMapping(value="/fjUpload.json" ,method=RequestMethod.POST)
    @ResponseBody
    public ResponseModel fjUpload(@RequestParam("file") MultipartFile file,HttpServletRequest request){
        PersonModel m = new PersonModel(); //自己的Model类,与我自己的业务逻辑处理有关
        ResponseModel model = new ResponseModel(); //自己封装的一个返回对象,可忽略。
            //获取jtbm
            String jtbm = request.getParameter("jtbm");
            //获取zjlx
            String zjlx = request.getParameter("zjlx");
            Integer intZjlx = Integer.parseInt(zjlx);

            //获取到文件名
            String fileName = file.getOriginalFilename();

            //将MultipartFile转换成流的形式存储
            InputStream in = file.getInputStream();
            //上传图片到ftp,获得服务器路径
            String serverPath = doSavePhoto(in,fileName);

            /*此处做自己的业务逻辑处理,可忽略*/
            //根据jtbm获取到该MraModel列表
            List<Map<String, Object>> list = daoHandler.executeSelectMoreSQL(sqlQuery("T_BD_BR_MRA",jtbm));
            if(intZjlx == 1){
                DatabaseTable dbt = new DatabaseTable(PersonModel.class);
                //循环遍历每一条记录,并执行更新语句
                for(Map<String,Object> map :list){
                    //将map结果集转换成POJO对象
                    m = (personModel) dbt.convertMap2POJO(map);
                    m.setNfsfzfj(serverPath);
                    daoHandler.update(m);
                }
            }
            model.success();
        }catch(Exception e){
            e.printStackTrace();
            system.out.println("Controller:发生异常!");
            model.error();
        }
        return model;
    }


    /**
     * 保存图片至ftp服务器
     * @param in input流
     * @param 图片名称
     * @return 服务器路径
     */
    public String doSavePhoto(InputStream in,String fileName){
        String serverPath = null;
        try{

            String wjm = DateUtil.nowTimestamp() + fileName.substring(fileName.lastIndexOf('.'));//图片以时间命名

                <!-- FtpConection单独建一个类-->
                FtpConection conection = new FtpConection(ftp服务器IP地址, ftp服务器端口, ftp服务器用户名, ftp服务器密码);
                //上传文件到服务器
                serverPath = wjm; 
                boolean flag = conection.uploadFiles(in, serverPath);<!--uploadFiles为一个方法,继续看-->
                conection.logout();
                if (flag) {
                    System.out.println("FTP存储成功!");
                } else {
                    System.out.println("FTP存储出错!");
                }

        }catch(Exception e){
            e.printStackTrace();
            System.out.println("Controller:上传ftp图片发生异常!");
        }
        return serverPath;
    }

注意:
- 在doSavePhoto(in,fileName);时,我把file类型转换成了InputStream流,这与我自己后面封装的FtpConection类、uploadFiles方法有关。先这么做好了。

4 辅助工具类即FtpConnection

/**
 * FTP服务器连接,用于访问FTP服务器,实现常用的创建目录、删除目录、上传文件、下载文件等操作。
 */
public class FtpConection {

    /**
     * 文件上次的缓存区大小
     */
    private static final int BUF_SIZE = 1024*1024;


    private String hostname;
    private Integer port;
    private String username;
    private String password;


    /**
     * 创建一个与FTP服务器的连接。
     * @param url 服务器IP地址
     * @param prot 服务端口
     * @param username 用户名
     * @param password 密码
     */
    public FtpConection(String url, Integer prot, String username, String password) {
        this.hostname = url;
        this.port = prot;
        this.username = username;
        this.password = password;
        client = new FTPClient();
        try {
            client.connect(hostname, port);
        } catch (SocketException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
            logger.error("FtpConection:链接FTP服务器发生异常!");
        }

        try {
            client.login(username, password);
        } catch (IOException e) {
            e.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
            logger.error("FtpConection:登陆FTP服务器发生异常!");
        }
    }


    /**
     * 利用流 上传文件
     * @param in 本地流
     * @param serverPath 服务器路径
     * @return True 文件上传成功,False 文件上传失败
     * @throws IOException
     */
    public boolean uploadFiles(InputStream in, String serverPath) throws IOException {
        boolean result = false;

        client.setFileType(FTP.BINARY_FILE_TYPE);
        client.enterLocalPassiveMode();
        client.setFileTransferMode(FTP.STREAM_TRANSFER_MODE);
        client.setBufferSize(BUF_SIZE);
        //此处可以解释 为什么把file装换成了InputStream流
        InputStream local = null;
        try {
            local = in;
            result = client.storeFile(serverPath, local);
        } finally {
            if (local != null) {
                local.close();
            }
        }

        return result;
    }

        /**
     * 退出已登录的FTP用户
     * @return Boolean值,true-退出成功,false-退出失败(连接为登录)。
     * @throws IOException
     */
    public boolean logout() throws IOException {
        return client.logout();
    }
}
到此为止,点击上传图片,就可以在你的ftp文件夹下看到上传的图片,经过Controller层的业务逻辑处理,可以把ftp服务器中的图片路径保存在数据库。检查一下你的数据库,检查一下你的ftp服务器文件夹。
对于如何访问到ftp服务器上的图片,下篇文章在做介绍。