美文网首页
分布式商城项目总结三之图片上传服务器的实现

分布式商城项目总结三之图片上传服务器的实现

作者: MisterDo | 来源:发表于2019-10-19 20:57 被阅读0次

3.图片上传

3.1. 图片服务器

3.1.1.传统项目中的图片管理

传统项目中,可以在web项目中添加一个文件夹,来存放上传的图片。例如在工程的根目录WebRoot下创建一个images文件夹。把图片存放在此文件夹中就可以直接使用在工程中引用。
优点:引用方便,便于管理
缺点:
1、如果是分布式环境图片引用会出现问题
2、图片的下载会给服务器增加额外的压力

传统图片服务器的实现.PNG
传统图片管理方式在分布式环境中的问题:
分布式的情况下,把工程复制多份到多个tomcat,由于负载均衡,每次上传的图片不一定都在一个tomcat中,因此会出现图片访问不到的情况
传统服务器上传图片出现的问题.PNG

3.1.2. 分布式环境的图片管理

图片服务器.PNG
不把图片存放在工程下,而是单独建立一个图片服务器,图片的上传与请求至于这个图片服务器有关
分布式环境一般都有一个专门的图片服务器存放图片。
我们使用虚拟机搭建一个专门的服务器来存放图片。在此服务器上安装一个nginx来提供http服务,安装一个ftp服务器来提供图片上传服务。

3.1.3 搭建图片服务器

第一步:安装vsftpd提供ftp服务

详见:vsftpd安装手册.doc

第二步:安装nginx提供http服务

详见:nginx安装手册.doc

1.1.1. 测试图片服务器

1. ftp服务测试。

a)使用ftp客户端

b)使用java程序
ftp可以需要依赖commons-net-3.3.jar包

public class TestFTP {

    @Test
    public void testFtpClient() throws IOException {  
        //创建一个FTP对象
        FTPClient ftpClient = new FTPClient();
        //创建ftp连接,默认端口为21
        ftpClient.connect("IP地址",21);
        //使用用户名和密码登录ftp服务器
        ftpClient.login("ftpuser","ftpuser");
        //读取本题文件
        FileInputStream inputStream = new FileInputStream(new File("D:\\tmp\\lq.jpg"));
        // 改变上传目录
      ftpClient.changeWorkingDirectory("/home/ftpuser/www/images");
        //设置文件格式为二进制     
        ftpClient.setFileType(FTP.BINARY_FILE_TYPE);
        //设置为被动模式,防止出现上传失败的情况
        ftpClient.enterLocalPassiveMode();
        //上传文件
        System.out.println(ftpClient.storeFile("h.jpg",inputStream));
         //断开ftp连接
        ftpClient.logout();
    }
}

上传成功后,可以直接通过浏览器进行访问,


测试ftp.PNG

3.1.5 SpringMVC中实现图片上传

上传思路:

第一步:

导入common-fileupload的依赖

<dependency>
        <groupId>commons-fileupload</groupId>
        <artifactId>commons-fileupload</artifactId>
</dependency>
第二步:

在SpringMVC配置文件中添加文件上传解析器

<bean id="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>

3.1.6. Service实现

1. 获取资源配置文件的内容

第一步.创建资源配置文件
配置文件.PNG
资源配置文件内容
FTP_ADDRESS=IP地址
FTP_PORT=21
FTP_USERNAME=ftpuser
FTP_PASSWORD=ftpuser
FTP_BASE_PATH=/home/ftpuser/www/images
第二步.获取资源配置文件
  • 在Spring(taotao-manage-dao.xml)容器中加载资源文件
<!-- 加载配置文件 -->
<context:property-placeholder location="classpath:resource/*.properties" />
  • 在Service中获取资源配置:
    @Value("${FTP_ADDRESS}")
    private String FTP_ADDRESS;
    @Value("${FTP_PORT}")
    private Integer FTP_PORT;
    @Value("${FTP_USERNAME}")
    private String FTP_USERNAME;
    @Value("${FTP_PASSWORD}")
    private String FTP_PASSWORD;
    @Value("${FTP_BASE_PATH}")
    private String FTP_BASE_PATH;

2. 图片名生成策略

  • 时间+随机数:
    /**
     * 图片名生成
     */
    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;
    }

  • 使用UUID
UUID.randomUUID();

3. Service实现


@Service
public class PictureServiceImpl implements PictureService {
    
    @Value("${FTP_ADDRESS}")
    private String FTP_ADDRESS;
    @Value("${FTP_PORT}")
    private Integer FTP_PORT;
    @Value("${FTP_USERNAME}")
    private String FTP_USERNAME;
    @Value("${FTP_PASSWORD}")
    private String FTP_PASSWORD;
    @Value("${FTP_BASE_PATH}")
    private String FTP_BASE_PATH;
    @Value("${IMAGE_BASE_URL}")
    private String IMAGE_BASE_URL;

    @Override
    public Map uploadPicture(MultipartFile uploadFile) {
        Map resultMap = new HashMap<>();
        try {
            //生成一个新的文件名
            //取原始文件名
            String oldName = uploadFile.getOriginalFilename();
            //生成新文件名
            //UUID.randomUUID();
            String newName = IDUtils.genImageName();
            newName = newName + oldName.substring(oldName.lastIndexOf("."));
            //图片上传
            String imagePath = new DateTime().toString("/yyyy/MM/dd");
            boolean result = FtpUtil.uploadFile(FTP_ADDRESS, FTP_PORT, FTP_USERNAME, FTP_PASSWORD, 
                    FTP_BASE_PATH, imagePath, newName, uploadFile.getInputStream());
            //返回结果
            if(!result) {
                resultMap.put("error", 1);
                resultMap.put("message", "文件上传失败");
                return resultMap;
            }
            resultMap.put("error", 0);
            resultMap.put("url", IMAGE_BASE_URL + imagePath + "/" + newName);
            return resultMap;
            
        } catch (Exception e) {
            resultMap.put("error", 1);
            resultMap.put("message", "文件上传发生异常");
            return resultMap;
        }
    }

}

3.1.7 Controller实现


@Controller
public class PictureController {

    @Autowired
    PictureService pictureService;

    @RequestMapping("/pic/upload")
    @ResponseBody
    public String  uploadFile(MultipartFile uploadFile){
        Map map = pictureService.uploadPicture(uploadFile);
        String json = JsonUtils.objectToJson(map);
        return json;
    }
}

注意:前端需要一个返回值,该返回值包含图片的url

相关文章

网友评论

      本文标题:分布式商城项目总结三之图片上传服务器的实现

      本文链接:https://www.haomeiwen.com/subject/czynmctx.html