二维码的创建与文件的上传与下载是密切相关的。因此我们先来看看文件的上传与下载。什么是文件的上传与下载呢?从本质上说,文件的上传与下载其实都是将文件从一个位置转移到另一个位置,只不过是转移的方向不同而已。我们可以通过下面的关系图来理解图片的上传和下载:
A--------------->B,如果A中有图片,B位置想要获取A的图片,那么得到图片的过程我们称之为A向B的图片上传;反过来,如果B中有图片,而A中没有图片,那么A-------------->B,即A从B位置获取图片的过程我们称之为A下载B位置的图片。在Web开发中,文件上传和下载是java web中常见的操作,文件上传主要是将文件通过IO流传放到服务器的某一个特定的文件夹下,而文件下载则是与文件上传相反,将文件从服务器的特定的文件夹下的文件通过IO流下载到本地。其本质都是利用了IO流的二进制数据的传输。
为了更好地理解图片的上传与下载,我们来举一个简单的例子,理解一下如何上传图片,并在浏览器端显示图片:
第一步:引入依赖
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.3.1</version>
</dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.5</version>
</dependency>
第二步:在spingmvc.xml中设置图片上传解析器
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<property name="maxUploadSize">
<value>52428800</value>
</property>
<property name="maxInMemorySize">
<value>100</value>
</property>
</bean>
注意,一定要配置这个图片上传解析器,否则报告下面的异常:
org.springframework.web.multipart.MultipartException: The current request is not a multipart request,另外,因此该异常的原因还有下面的几种情况:
(1)使用get方式进行图片上传,对于文件上传必须使用post方式进行上传,因为图片二进制内容比较多,get方式无法满足。
(2)如果控制层中使用的是MultipartFile multipartFile来接收图片的二进制信息,那么表单元素必须定义enctype="multipart/form-data"属性,否则也会报告上面的异常。
(3)MultipartFile multipartFile的multipartFile变量需要与的name属性值保持一致,否则也会报告下面的空指针异常:
Servlet.service() for servlet [springmvc] in context with path [/yx-web] threw exception [Request processing failed; nested exception is java.lang.NullPointerException] with root cause
例1
@RequestMapping(value="/fileUpload",method={RequestMethod.POST})
public void fileUpload(HttpServletResponse response, HttpServletRequest request,MultipartFile multipartFile) throws Exception {
//接收客户端获取的图片流
InputStream in = multipartFile.getInputStream();
//将图片以二进制流的方式返回给客户端,也就是对应下载过程,即客户端下载客户端所选中的那张图片
OutputStream out = response.getOutputStream();
byte[] b = new byte[1024*1024];
int length;
while((length = in.read(b)) != -1){
out.write(b);
}
out.flush();
out.close();
}
例2—图片上传
@RequestMapping(value="/fileUpload2",method={RequestMethod.POST})
public void fileUpload2(HttpServletResponse response, HttpServletRequest request,MultipartFile multipartFile) throws Exception {
//定义文件上传路径
String picName = multipartFile.getOriginalFilename();
String uploadFilePath = "C:\\Users\\Administrator\\Desktop\\"+picName;
File file = new File(uploadFilePath);
//图片的二进制流存储在multipartFile对象中,我们可以调用transferTo方法来上传multipartFile所携带的文件
multipartFile.transferTo(file);
}
例3—图片下载
//从桌面图片下载到桌面的test1目录中
@RequestMapping(value="/fileDownload",method={RequestMethod.POST})
public void fileDownload(HttpServletResponse response, HttpServletRequest request,MultipartFile multipartFile){
//目标下载文件
String picName = "f44a5e0ee9d8709e10e6d27a006f1235_t01dc83a33b3df82892.jpg";
//下载到哪里
String uploadFilePath = "C:\\Users\\Administrator\\Desktop\\test1";
//从哪里下载
String fromFilePath = "C:\\Users\\Administrator\\Desktop";
File filePath = new File(uploadFilePath);
if(!filePath.exists()){
//创建目录
filePath.mkdirs();
}
File fromFile = new File(fromFilePath, picName);
File targetFile = new File(filePath, picName);
//判断文件是否存在
if(fromFile.exists() && !targetFile.exists()){
OutputStream out = null;
try{
InputStream in = new FileInputStream(fromFile);
out = new FileOutputStream(targetFile);
int len;
while((len = in.read())!=-1){
out.write(len);
}
}catch(Exception e){
e.printStackTrace();
}finally{
if(null != out){
try {
out.flush();
out.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
例4—客户端下载某个盘符下的图片
//从桌面图片下载到客户端中
@RequestMapping(value="/fileDownload2")
public void fileDownload2(HttpServletResponse response, HttpServletRequest request){
try{
//定义文件上传路径
String picName = "f44a5e0ee9d8709e10e6d27a006f1235_t01dc83a33b3df82892.jpg";
String fromFilePath = "C:\\Users\\Administrator\\Desktop";
File fromFile = new File(fromFilePath, picName);
//接收客户端获取的图片流
InputStream in = new FileInputStream(fromFile);//multipartFile.getInputStream();
//将图片以二进制流的方式返回给客户端,也就是对应下载过程,即客户端下载客户端所选中的那张图片
OutputStream out = response.getOutputStream();
byte[] b = new byte[1024*1024];
int length;
while((length = in.read(b)) != -1){
out.write(b);
}
out.flush();
out.close();
}catch(Exception e){
e.printStackTrace();
}
}
这时我们在客户端中输入下面的访问路径,即可以访问从桌面上下载到的图片:
http://localhost:8080/yx-web/test/yx/fileDownload2
注意: <img src="${pageContext.request.contextPath}/test/yx/fileDownload2">是一个get请求。