3.图片上传
3.1. 图片服务器
3.1.1.传统项目中的图片管理
传统项目中,可以在web项目中添加一个文件夹,来存放上传的图片。例如在工程的根目录WebRoot下创建一个images文件夹。把图片存放在此文件夹中就可以直接使用在工程中引用。
优点:引用方便,便于管理
缺点:
1、如果是分布式环境图片引用会出现问题
2、图片的下载会给服务器增加额外的压力
传统图片管理方式在分布式环境中的问题:
分布式的情况下,把工程复制多份到多个tomcat,由于负载均衡,每次上传的图片不一定都在一个tomcat中,因此会出现图片访问不到的情况
3.1.2. 分布式环境的图片管理
不把图片存放在工程下,而是单独建立一个图片服务器,图片的上传与请求至于这个图片服务器有关
分布式环境一般都有一个专门的图片服务器存放图片。
我们使用虚拟机搭建一个专门的服务器来存放图片。在此服务器上安装一个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();
}
}
上传成功后,可以直接通过浏览器进行访问,
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. 获取资源配置文件的内容
第一步.创建资源配置文件
资源配置文件内容
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
网友评论