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

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

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 225,677评论 6 524
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 96,772评论 3 408
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 173,108评论 0 370
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 61,378评论 1 303
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 70,394评论 6 403
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 53,807评论 1 315
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 42,127评论 3 432
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 41,136评论 0 281
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 47,693评论 1 328
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 39,703评论 3 349
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 41,810评论 1 357
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 37,400评论 5 352
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 43,130评论 3 341
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 33,532评论 0 25
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 34,707评论 1 278
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 50,412评论 3 383
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 46,892评论 2 368

推荐阅读更多精彩内容

  • FTP服务概述 简单FTP构建及访问 VSFTP服务基础 用户禁锢、黑白名单 FTP并发及带宽限制 一、FTP服务...
    紫_轩阅读 7,635评论 3 25
  • ftp 文件传输协议 跨平台 上传下载文件 vsftpd 工具:非常安全的文件传输协议;默认的命令端口21号,数据...
    柒夏锦阅读 4,051评论 1 9
  • 图片更清晰,文字在最下面 FTP是TCP/IP的一种应用,使用TCP而不是UDP,所以是可靠的,面向连接的。 FT...
    停下浮躁的心阅读 1,727评论 0 4
  • 291976-陈国艳《2017-07-04》 【连续第143天总结】 A、目标完成情况 1、抄写概念一遍完成100...
    国艳更文的365天阅读 229评论 2 0
  • 哇唔,这里太漂亮了! 美不胜收,就像一座水晶宫殿。 可是一个很严肃的问题出现了, 那些冰柱都是断的,谁把它弄断的?...
    愚人传说阅读 199评论 1 1