基于目前商城项目的开发,需要将图片上传至Nginx+VSFTP搭建的图片服务器,如果你只想了解如何使用java实现将图片等文件上传至VSFTP服务器,可以直接参考相关上传代码即可,要不然看起来会有点复杂,因为涉及到多服务器、存在跨域问题,以下是关于本案例的一些说明:
1、前端是基于Vue+ElementUI
,后端是基于SpringBoot
2、前后端分离,前端项目放在81
端口的Nginx服务器上,后端项目部署在8080
端口的tomcat服务器上
3、Nginx+VSFTP搭建的图片服务器是在ip为192.168.223.128
的Linux虚拟机上,关于其搭建可参考:
一、前期准备 1、环境准备:我这里使用的是CentOS7 64位Linux操作系统 2、安装与配置Nginx服 […]
参考ElementUI官网上传图片的组件,我这里选择手工上传的组件,在前端项目中新建了Upload.vue
,代码如下:
<template> <div> <el-upload class="upload-demo" ref="upload" action="http://localhost:81/admin/file/upload" :on-preview="handlePreview" :on-remove="handleRemove" :file-list="fileList" :auto-upload="false"> <el-button slot="trigger" size="small" type="primary">选取文件</el-button> <el-button style="margin-left: 10px;" size="small" type="success" @click="submitUpload">上传到服务器</el-button> <div slot="tip" class="el-upload__tip">只能上传jpg/png文件,且不超过500kb</div> </el-upload> </div> </template> <script> export default { data(){ return { fileList: [] }; }, methods:{ submitUpload() { this.$refs.upload.submit(); } } } </script> <style scoped> </style>
注意这里的action
请求是发送到http://localhost:81/admin/file/upload
,前端项目的部署在81
端口的Nginx服务器,如果直接发送给8080的tomcat服务器,会存在跨域问题,关于跨域问题请参考:
文章目录 总结 在进行前端网页开发尤其是在调用接口时经常会遇到跨域问题,导致接口调用失败(浏览器端类似报错如下 […]
因此,我在81
端口的Nginx服务器上配置了反向代理,具体部分配置如下(匹配/admin/转发到8080):
listen 81; server_name localhost; #charset koi8-r; #access_log logs/host.access.log main; location / { root html; index index.html index.htm; } location /admin/ { proxy_pass http://127.0.0.1:8080; }
1、在pom.xml中引入commons-net
用于FTP上传的jar包,这里我使用的是3.7.2版本,具体坐标如下:
<dependency> <groupId>commons-net</groupId> <artifactId>commons-net</artifactId> <version>3.7.2</version> </dependency>
2、在application.yml
配置文件中新增ftp
相关配置,如下:
#ftp配置 ftp: #ftp所在主机ip或主机名 host: 192.168.223.128 #ftp端口号 port: 21 #ftp请求的用户名 username: panziye #ftp请求的密码 password: 123456 #ftp根路径 我这里设为/www basePath: /www
3、在util包下新建FtpUtil.java
,具体代码如下:
package com.panziye.shop.util; import org.apache.commons.net.ftp.FTP; import org.apache.commons.net.ftp.FTPClient; import org.apache.commons.net.ftp.FTPReply; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.stereotype.Component; import java.io.IOException; import java.io.InputStream; import java.util.StringTokenizer; @Component @ConfigurationProperties(prefix = "ftp") public class FtpUtil { private String host; private Integer port; private String username; private String password; private String basePath; /** * 上传文件 * @param filePath 文件上传目录 * @param fileName 文件上传后名称 * @param inputStream 文件流 * @return */ public Boolean uploadFile(String filePath,String fileName, InputStream inputStream) { //1、目标上传路径 String targetPath = basePath+filePath; //2、创建FTPClient对象 FTPClient ftp = new FTPClient(); try { //3、定义返回的状态码 int reply; //4、连接ftp ftp.connect(host,port); //5、输入账号和密码进行登录 ftp.login(username, password); //6、接受状态码(如果成功,返回230,如果失败返回503) reply = ftp.getReplyCode(); //7、根据状态码检测ftp的连接,如果连接成功返回true,否则返回false if (!FTPReply.isPositiveCompletion(reply)) { //说明连接失败,需要断开连接 ftp.disconnect(); return false; } // 8、切换工作目录,成功返回true,否则返回false if(!ftp.changeWorkingDirectory(targetPath)){ //切换不成功表示目录不存在,则创建该目录并切换进去 boolean f = createDirecroty(targetPath,ftp); ftp.changeWorkingDirectory(targetPath); } //9、设置被动模式(根据自己ftp的设置来决定,默认是主动模式) //模式错误可能会导致上传超时,文件大小为0的情况 ftp.enterLocalPassiveMode(); //10、把文件转换为二进制字符流的形式进行上传 ftp.setFileType(FTP.BINARY_FILE_TYPE); //11、上传文件到该目录 ftp.storeFile(fileName,inputStream); //12、关闭输入流 inputStream.close(); // 13.退出ftp ftp.logout(); }catch (Exception e){ e.printStackTrace(); }finally { if (ftp.isConnected()) { try { // 14.断开ftp的连接 ftp.disconnect(); } catch (Exception ioe) { ioe.printStackTrace(); } } } return true; } //创建多层目录文件 public Boolean createDirecroty(String remote, FTPClient ftp) throws IOException { boolean flag = true; StringTokenizer s = new StringTokenizer(remote, "/"); s.countTokens(); String pathName = ""; while (s.hasMoreElements()) { pathName = pathName + "/" + (String) s.nextElement(); try { ftp.makeDirectory(pathName); } catch (Exception e) { e.printStackTrace(); flag = false; } } return flag; } public void setHost(String host) { this.host = host; } public void setPort(Integer port) { this.port = port; } public void setUsername(String username) { this.username = username; } public void setPassword(String password) { this.password = password; } public void setBasePath(String basePath) { this.basePath = basePath; } }
4、新建FileController.java
测试类,代码如下:
package com.panziye.shop.controller; import com.panziye.shop.http.ResponseResult; import com.panziye.shop.util.FtpUtil; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.*; import org.springframework.web.multipart.MultipartFile; import java.io.IOException; import java.util.UUID; @RestController @RequestMapping("/admin/file") public class FileController { @Autowired private FtpUtil ftpUtil; @PostMapping("/upload") public ResponseResult upload(MultipartFile file){ //图片保存路径:后期可以定义到常量类中,时间目录可以动态生成,以便复用和修改 String filePath = "/images/2020"; //图片原名称 String originalName = file.getOriginalFilename(); //生成随机名称 String fileName = UUID.randomUUID()+originalName.substring(originalName.lastIndexOf(".")); try { //上传 ftpUtil.uploadFile(filePath,fileName,file.getInputStream()); } catch (IOException e) { e.printStackTrace(); } //可以返回图片相对路径 return ResponseResult.ok(); } }
5、选择图片,点击上传至服务器,测试上传
连接图片服务器发现目录成功创建,图片成功上传