Loading [MathJax]/jax/input/TeX/config.js
前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >专栏 >Java实现把图片上传到图片服务器(nginx+vsftp)前言:需求:功能实现:总结:

Java实现把图片上传到图片服务器(nginx+vsftp)前言:需求:功能实现:总结:

作者头像
贪挽懒月
发布于 2018-06-08 07:38:31
发布于 2018-06-08 07:38:31
4.2K00
代码可运行
举报
文章被收录于专栏:JavaEEJavaEE
运行总次数:0
代码可运行

前言:

在我另一篇笔记中已经记载了如何用nginx + vsftp搭建图片服务器(请参考nginx + vsftp搭建图片服务器),并且用vsftp的客户端工具filezilla测试过已经可用。但是在开发中应该是把用户在前端页面提交的图片保存到图片服务器中,接下来就来实现这个功能。

需求:

用户在页面中上传一张图片,把图片保存到图片服务器,把图片的url保存到user表中,复制user表中的图片url在浏览器中可访问到用户上传的图片。

功能实现:

一、数据库设计:

图片发自简书App

二、项目设计:

为了快速开发,本案例使用springboot + mybatis实现。项目结构如下:

图片发自简书App

1、添加依赖:

pom.xml:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
<!-- 文件上传 -->
        <dependency>
            <groupId>commons-fileupload</groupId>
            <artifactId>commons-fileupload</artifactId>
            <version>1.3.2</version>
        </dependency>
        <dependency>
            <groupId>commons-io</groupId>
            <artifactId>commons-io</artifactId>
            <version>2.4</version>
        </dependency>
        <dependency>
            <groupId>commons-net</groupId>
            <artifactId>commons-net</artifactId>
            <version>3.3</version>
        </dependency>
        <!-- 时间操作组件 -->
        <dependency>
            <groupId>joda-time</groupId>
            <artifactId>joda-time</artifactId>
            <version>2.5</version>
        </dependency>
<!-- mybaties -->
        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
            <version>1.3.2</version>
        </dependency>
        <!-- mysql -->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <scope>runtime</scope>
        </dependency>

2、配置:

application.properties:

注意,下面的basepath配置的是文件上传的根路径,/home/ftpuser/images,图片都传到这个目录或其子目录下,baseUrl是访问图片时的基础Url,因为在搭建图片服务器时我们设置了访问根目录是/home/ftpuser,所以访问的基础url就是192.168.xx.xxx/images

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
#配置数据库连接信息
spring.datasource.url=jdbc:mysql:///db_demo?useUnicode=true&characterEncoding=utf8
spring.datasource.username=#
spring.datasource.password=#
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
#Mybatis扫描接口对应的xml文件
mybatis.mapper-locations=classpath:mappers/*.xml
#起别名。可省略写mybatis的xml中的resultType的全路径  
mybatis.type-aliases-package=com.zhu.pojo
#配置文件上传器
spring.http.multipart.maxFileSize=100Mb
spring.http.multipart.maxRequestSize=100Mb
#ftp相关配置
FTP.ADDRESS=192.168.xx.xxx
FTP.PORT=21
FTP.USERNAME=ftpuser
FTP.PASSWORD=ftpuser
FTP.BASEPATH=/home/ftpuser/images
#图片服务器相关配置
IMAGE.BASE.URL=http://192.168.xx.xxx/images
#视图解析器
spring.mvc.view.prefix=/pages/
spring.mvc.view.suffix=.html

3、实体类:

省略set和get方法。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public class User {
    private Integer uid;

    private String username;

    private String password;

    private String picture;
}

4、dao层:

UserMapper.java

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public interface UserMapper {
        int insert(User record);
}

UserMapper.xml

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
<insert id="insert" parameterType="com.zhu.pojo.User">
    insert into user (uid, username, password, 
      picture)
    values (#{uid,jdbcType=INTEGER}, #{username,jdbcType=CHAR}, #{password,jdbcType=CHAR}, 
      #{picture,jdbcType=CHAR})
  </insert>

5、service层:

service层只是简单的调用dao层,保存user对象。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
@Service
public class UserServiceImpl implements UserService{

    @Autowired
    private UserMapper userMapper;
    
    @Override
    public void insertUser(User user) {
        userMapper.insert(user);
        
    }

}

6、utils:

①、FtpUtils.java:

我们知道filezilla是vsftp客户端工具,输入ip、端口、vsftp用户的用户名和密码就可以连接上服务。那么在Java中,我们就new一个客户端,除了需要传入以上四个值外,还需要基础目录、文件存放路径和文件io流。还有一点特别注意,一定要加上ftp.enterLocalPassiveMode()设置被动模式,否则的话会出现图片传到服务器上去了,但是大小一直是0。这个方法的意思就是每次数据连接之前,ftp client告诉ftp server开通一个端口来传输数据。为什么要这样做呢,因为ftp server可能每次开启不同的端口来传输数据,但是在linux上或者其他服务器上面,由于安全限制,可能某些端口没有开启,所以就出现阻塞。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public class FtpUtil {

    /** 
     * Description: 向FTP服务器上传文件 
     * @param host FTP服务器ip
     * @param port FTP服务器端口 
     * @param username FTP登录账号 
     * @param password FTP登录密码 
     * @param basePath FTP服务器基础目录,/home/ftpuser/images
     * @param filePath FTP服务器文件存放路径。例如分日期存放:/2018/05/28。文件的路径为basePath+filePath
     * @param filename 上传到FTP服务器上的文件名 
     * @param input 输入流 
     * @return 成功返回true,否则返回false 
     */  
    public static boolean uploadFile(String host, int port, String username, String password, String basePath,
            String filePath, String filename, InputStream input) {
        boolean result = false;
        FTPClient ftp = new FTPClient();
        try {
            int reply;
            ftp.connect(host, port);// 连接FTP服务器
            // 如果采用默认端口,可以使用ftp.connect(host)的方式直接连接FTP服务器
            ftp.login(username, password);// 登录
            reply = ftp.getReplyCode();
            if (!FTPReply.isPositiveCompletion(reply)) {
                ftp.disconnect();
                return result;
            }
            //切换到上传目录
            if (!ftp.changeWorkingDirectory(basePath+filePath)) {
                //如果目录不存在创建目录
                String[] dirs = filePath.split("/");
                String tempPath = basePath;
                for (String dir : dirs) {
                    if (null == dir || "".equals(dir)) continue;
                    tempPath += "/" + dir;
                    if (!ftp.changeWorkingDirectory(tempPath)) {
                        if (!ftp.makeDirectory(tempPath)) {
                            return result;
                        } else {
                            ftp.changeWorkingDirectory(tempPath);
                        }
                    }
                }
            }
            //设置为被动模式
            ftp.enterLocalPassiveMode();
            //设置上传文件的类型为二进制类型
            ftp.setFileType(FTP.BINARY_FILE_TYPE);
            //上传文件
            if (!ftp.storeFile(filename, input)) {
                return result;
            }
            input.close();
            ftp.logout();
            result = true;
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (ftp.isConnected()) {
                try {
                    ftp.disconnect();
                } catch (IOException ioe) {
                }
            }
        }
        return result;
    }
}

②、IDUtils.java:

这个工具类是用来生成随机的文件名。因为用户上传的时候,可能文件名是一致的,比如A用户上传了名为a.jpg的图片,B用户也上传了名为a.jpg的图片的话就会上传失败,会提示文件已存在。所以需要生成一个随机的文件名保证不重名。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public class IDUtils {

    /**
     * 生成随机图片名
     */
    public static String genImageName() {
        //取当前时间的长整形值包含毫秒
        long millis = System.currentTimeMillis();
        //long millis = System.nanoTime();
        //加上三位随机数
        Random random = new Random();
        int end3 = random.nextInt(999);
        //如果不足三位前面补0
        String str = millis + String.format("%03d", end3);
        
        return str;
    }
}

7、controller:

在springmvc中,前端页面提交的图片信息会自动封装在MultipartFile对象中,在这个controller中的通过MultipartFile对象获取图片本来的文件名,然后截取后缀,用工具类生成新的文件名,再把后缀拼接上,然后通过@Value注解获取application.properties中配置的ftp相关的配置的值,调用ftp工具类进行图片的上传,调用service把用户信息保存到数据库

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
@Controller
public class UserContrller {

    @Value("${FTP.ADDRESS}")
    private String host;
    // 端口
    @Value("${FTP.PORT}")
    private int port;
    // ftp用户名
    @Value("${FTP.USERNAME}")
    private String userName;
    // ftp用户密码
    @Value("${FTP.PASSWORD}")
    private String passWord;
    // 文件在服务器端保存的主目录
    @Value("${FTP.BASEPATH}")
    private String basePath;
    // 访问图片时的基础url
    @Value("${IMAGE.BASE.URL}")
    private String baseUrl;

    @Autowired
    private UserService userService;

    @RequestMapping("/pic/upload")
    @ResponseBody
    public String pictureUpload(
            @RequestParam("pic") MultipartFile uploadFile,
            @RequestParam("username")String username,
            @RequestParam("password") String password) {
        try {
            //1、给上传的图片生成新的文件名
            //1.1获取原始文件名
            String oldName = uploadFile.getOriginalFilename();
            //1.2使用IDUtils工具类生成新的文件名,新文件名 = newName + 文件后缀
            String newName = IDUtils.genImageName();
            newName = newName + oldName.substring(oldName.lastIndexOf("."));
            //1.3生成文件在服务器端存储的子目录
            String filePath = new DateTime().toString("/yyyy/MM/dd");
            
            //2、把前端输入信息,包括图片的url保存到数据库
            User user = new User();
            user.setUsername(username);
            user.setPassword(password);
            user.setPicture(baseUrl + filePath + "/" + newName);
            userService.insertUser(user);
            
            //3、把图片上传到图片服务器
            //3.1获取上传的io流
            InputStream input = uploadFile.getInputStream();
            
            //3.2调用FtpUtil工具类进行上传
            boolean result = FtpUtil.uploadFile(host, port, userName, passWord, basePath, filePath, newName, input);
            if(result) {
                return "success";
            }else {
                return "false";
            }
        } catch (IOException e) {
            return "false";
        }
    }

}

8、index.html:

这个页面只有一点需要注意,那就是form中需要加上enctype="multipart/form-data",不然controller中通过MultipartFile获取不到图片信息。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>

  <form action="/pic/upload" enctype="multipart/form-data" method="post">
       <input type="text" name="username"><br>
       <input type="password" name="password"><br>
       <input type="file" name="pic"><br>
       <input type="submit" value="提交">
   </form>

</body>
</html>

9、测试:

①:先用filezilla连上vsftp,看看上传之前的目录结构:

图片发自简书App

②:运行项目,上传文件:

图片发自简书App

图片发自简书App

③:返回了success,再到filezilla中刷新一下,看看图片是否成功上传到服务器:

图片发自简书App

④:已经上传成功了。再看看数据表中的信息:

图片发自简书App

⑤:再复制数据表中保存的图片url到浏览器中。看看能否访问到图片:

图片发自简书App

成功访问到了刚才上传的图片!

总结:

1、过程梳理:

先搭建起项目,在html页面中通过<input type="file">上传文件,在controller中通过MultipartFile对象接收图片信息,然后获取原文件名,调用IDUtis工具类生成新的文件名,调用joda-time时间组件获取当前时间作为图片在服务器端保存的目录,然后用@Value读取在application.properties中的配置信息,拼接出图片的url,调用service保存到数据库中。最后调用ftp工具类,new了一个ftp的客户端,传入相关参数,把图片上传到图片服务器。

2、避坑说明:

在上面已经说过了,在ftp工具类中,一定要加上ftp.enterLocalPassiveMode()设置被动模式,不然上传到服务器的就是空文件,大小一直是0字节。

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2018.05.30 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
Java 上传文件到ftp服务器「建议收藏」
前两篇文章我们搭建了一个ftp服务器,并对服务器进行了相应的配置,这篇文章我们来说一下我们如何上传文件。
全栈程序员站长
2022/10/03
3.6K0
Java 上传文件到ftp服务器「建议收藏」
VSFTPD技术
2、在pom.xml通过坐标引入相关jar包( 该jar用于将文件封装成字节流的数据传输的功能 )
时间静止不是简史
2020/07/27
2.2K0
VSFTPD技术
如何快速搭建图片服务器[通俗易懂]
分布式集群的项目, 正常一般的工程是把图片放在web项目的自身服务器的工程中,但在集群环境下,会出现找不到图片的情况。
全栈程序员站长
2022/07/25
4.7K0
如何快速搭建图片服务器[通俗易懂]
nginx+vsftp搭建图片服务器前言:简介:nginx的安装:vsftp的安装:配置nginx为图片服务器:总结:
前言: 在分布式架构中,往往会有多个tomcat,然后你上传的图片只是在其中的某一个tomcat,你访问时是有集群的tomcat随机提供服务。当你访问的tomcat是有图片的那个时,图片能正常显示,如果恰巧是那个没有图片的tomcat时,图片就不能正常显示。这就完成了访问同一个图片,可能你刷新一次可以访问,再刷新一次图片就访问不到了。这时,我们就需要一个服务器用来专门存储图片,一般我们都用nginx。 简介: 1、nginx: Nginx是一款轻量级的Web 服务器/反向代理服务器及电子邮件(IMAP/PO
贪挽懒月
2018/06/13
2.9K0
Nginx 搭建图片服务器
本章内容通过Nginx 和 FTP 搭建图片服务器。在学习本章内容前,请确保您的Linux 系统已经安装了Nginx和Vsftpd。
芋道源码
2019/05/09
6.6K0
Nginx 搭建图片服务器
JAVA 实现 FTP 文件上传、下载和删除
项目中可能经常会遇到需要文件上传到服务器上,需要的时候从服务器获取。结合之前的博客 阿里云服务器上搭载 FTP 站点 本篇博客记录:如何通过java 实现FTP文件上传下载和删除功能。虽然网上有很多教程,但是或多或少都会有些问题。看到本篇文章,也许会让你少踩坑哦~
AI码真香
2022/09/13
1.7K0
JAVA 实现 FTP 文件上传、下载和删除
基于VSFTPD技术与KindEditor的简单案例
1.创建图片上传的service,service实现类,controller(已实现) 2.下载KindEditor,放到静态资源中,并通过script标签指定(注意核实路径,js指定后需要重启项目)
时间静止不是简史
2020/07/27
1.6K0
基于VSFTPD技术与KindEditor的简单案例
java实用工具类——使用java代码实现ftp上传下载工具类
小编最近忙着学习项目构架上的一些技术,把实用的工具类整理下,单独放在一个项目。其他项目需要用直接使用maven依赖一下就可以使用了。项目中需要实现上传多张图片,由于多张图片,又担心并发量大。所以小编做了一个负载均衡,把上传后的图片保存到linux上的ftp中去,不了解linux上的ftp小编后期编写个教程。
全栈程序员站长
2022/08/12
2.2K0
商品管理系统_营销系统四大系统
项目开发使用SSM(Mybatis + Spring + Springmvc)实现商品管理相关功能,MySQL作为后台数据库。功能包括查询商品列表,添加商品信息等,具体要求如下:
全栈程序员站长
2022/09/20
5900
ftp文件上传及下载工具类[通俗易懂]
1、ftp文件上传用例解析(需使用apacher的commons-net-3.3.jar)
全栈程序员站长
2022/09/06
2.2K0
基于spring boot sftp文件上传
对sftp文件上传将行封装,实现连接的单例模式,完成线程安全的改进,sftp文件上传下载失败的重试。
张泽旭
2018/12/10
2.9K0
Nginx 搭建FTP图片服务器
1、http服务:可以使用nginx做静态资源服务器。也可以使用apache。推荐使用nginx,效率更高。
用户5760343
2022/05/24
8.4K0
Nginx 搭建FTP图片服务器
【java基础】压缩图片上传
1、pom.xml <dependency> <groupId>net.coobird</groupId> <artifactId>thumbnailator</artifactId> <version>0.4.8</version> </dependency> 2、代码 /** * 上传图片 */ @RequestMapping(method = RequestMethod.POST, value = "upload") public Object Upload
用户5640963
2019/07/25
1.8K0
使用Nginx和vsftpd搭建图片服务器
安装完后,有/etc/vsftpd/vsftpd.conf 文件,是vsftp的配置文件。 [root@linuxidc ~]# yum -y install vsftpd
星哥玩云
2022/07/26
5520
Spring高级技术应用——百战商城实现(上)
创建common_mapper, 选中父项目 ,ctrl+n ,Maven module,建子模块项目,存放实体类 (common_pojo, common_mapper),common_mapper需要额外添加坐标
时间静止不是简史
2020/07/27
2K0
Spring高级技术应用——百战商城实现(上)
图片服务器搭建
1. 分析需求图片服务器的原因 在网站开发过程中使用tomcat集群时,可能存在在一个tomcat服务器中上传,在另外一个tomcat中进行访问,这样就会导致资源访问失败,而很好的解决这一问题的方法,就是搭建一个专门的服务器来实现文件的存储与读。 2. 搭建环境 Linux CentosOS6.3 Nginx Vsftbd FileZilla 3.安装http服务 3.1.安装Linux虚拟机 这个过程就不作详细讲解,翻阅网上资料,值得注意是在安装过程中,容易出现连不上,这就需要将网卡配置进行修改    
cfs
2018/03/08
6.6K0
如何在Ubuntu 18.04上使用VSFTP快速设置FTP服务器
如果你想将应用程序迁移到最新版本Ubuntu Linux服务器中,并且需要快速启动并运行FTP服务器。如何操作?这实际上非常简单。这里将使用VSFTP服务器向您展示如何做到这一点。
星哥玩云
2022/07/14
1.9K0
【摸鱼高手】搭个自己的FTP服务器玩玩
  在搭建FTP服务器之前,先跟大家介绍下什么是FTP服务器,**不然怕有些小伙伴可能只是有个模糊的概念,学习要尽量知其然,知其所以然,不要一知半解,否则自己用着也不踏实。**
IT学习日记
2022/09/13
1.9K0
【摸鱼高手】搭个自己的FTP服务器玩玩
Java常用工具类整合
CSDN加速:https://codechina.csdn.net/mirrors/evil0ps/utils 源码和jar见:https://github.com/evil0ps/utils
JokerDJ
2023/11/27
3330
【图文教程】云服务器上,Linux安装VSFTPD组件及遇到的问题
服务器做迁移,从AXX云迁移到Txx云上,迁移的话,需要把图片服务器也迁移过去。之前使用的是VSFTPD这次也还用这个吧。这里就记录下FTP服务器安装及遇到的问题。
凯哥Java
2023/01/12
1.5K0
【图文教程】云服务器上,Linux安装VSFTPD组件及遇到的问题
相关推荐
Java 上传文件到ftp服务器「建议收藏」
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
查看详情【社区公告】 技术创作特训营有奖征文
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验