Java向服务器上传图片

在比较绚丽多彩的网站或者业务逻辑比较丰富的程序设计过程中,图片的相关操作时必不少的,尤其时图片的上传。还没有彻底摆脱纸质办公可能需要将纸质的文件备份上传,网站的建设可能需要上传用户头像、图片描述等等,这些都需要将图片从本地上传到网上(服务器)。下面将介绍笔者今天在做图片上传过程中所遇到的坑~

一、业务描述

  业务要求是将机器在不断生产的照片上传到网上,以便于能在网站上查看。

二、解决思路

  由于对图片这一块的处理已经比较生疏,所以打算一点一点解决这些业务需求。首先将业务分解为以下几个部分:

  (1)服务器接收浏览器端上传的图片。这一点比较好实现,因为服务器端的开发大多数都是基于B/S架构的,也就是逻辑与浏览器端进行开发的。

  (2)服务器接收客户端上传的图片。这一点看似也不难,但是如何正确的发送出数据确是有点难度,也是笔者今天踩坑的地方。

  (3)业务逻辑的优化完善。

三、服务器接收浏览器端上传的图片

  1、新建网页

 1 <!DOCTYPE html>
 2 <html>
 3 <head>
 4 <meta charset="UTF-8">
 5 <title>图片上传</title>
 6 </head>
 7 <body>
 8     <form action="/plant/upload.action" enctype="multipart/form-data"
 9         method="post">
10         图片:<input type="file" name="img"/> <br/>
11         <input type="submit" value="上传"/>
12     </form>
13 </body>
14 </html>
查看代码

  此处需要注意的是 form标签enctype属性的添加,还有就是input输入框中name属性的设置,这与后台的代码相对应。    

  2、编写Controller层的代码

 1 @Controller
 2 public class UploadController {
 3 
 4     @RequestMapping(value="/upload",method=RequestMethod.POST)
 5     @ResponseBody
 6     public String uploadImg(@RequestParam("img") MultipartFile img, HttpServletRequest request,HttpServletResponse response) {
 7         String contentType = img.getContentType();    // 获取文件的类型
 8         System.out.println("文件类型为:" +  contentType);
 9         String originalFilename = img.getOriginalFilename();     // 获取文件的原始名称
10         // 判断文件是否为空
11         if(!img.isEmpty()) {
12             File targetImg = new File("F:/img");
13             // 判断文件夹是否存在
14             if(!targetImg.exists()) {
15                 targetImg.mkdirs();    //级联创建文件夹
16             }
17             try {
18                 // 开始保存图片
19                 FileOutputStream outputStream = new FileOutputStream("F:/img/" + originalFilename);
20                 outputStream.write(img.getBytes());
21                 outputStream.flush();
22                 outputStream.close();
23             } catch (IOException e) {
24                 e.printStackTrace();
25             }
26         }
27         return "SUCCESS";
28     }
29 }
查看代码

   3、Spring配置文件的修改和项目依赖的添加(小坑)

1 <!-- 文件上传组件 -->
2 <dependency>
3     <groupId>commons-fileupload</groupId>
4     <artifactId>commons-fileupload</artifactId>
5     <version>1.3.1</version>
6 </dependency>
查看代码
1 <!-- 支持文件上传 -->
2 <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
3      <!-- 请求编码格式 -->
4      <property name="defaultEncoding" value="utf-8"></property>
5      <!-- 上传文件大小(单位:字节) -->
6      <property name="maxUploadSize" value="50000000"></property>
7      <!-- 缓冲区大小(单位:KB) -->
8      <property name="maxInMemorySize" value="1024"></property>
9 </bean>
查看代码

  4、启动项目,打开浏览器显示相应的图片上传的网页,选择图片,点击上传,如果不出以外的化本地路径上应该会看到刚刚上传的图片。

四、服务器接收客户端上传的图片

  网上有不少内容关于本部分都是介绍使用HttpURLConnection进行上传,这中方法一是比较复杂,需要自己手动封装请求,洋洋洒洒几十行代码;二是如果项目比较复杂,用到Session或者Cookie的话,那就真没辙了~

  基于上述原因,本文选择使用HttpClient进行本地图片的上传

  1、引入相关的依赖

 1 <dependency>
 2     <groupId>org.apache.httpcomponents</groupId>
 3     <artifactId>httpclient</artifactId>
 4     <version>4.5.3</version>
 5 </dependency>
 6 <dependency>
 7     <groupId>org.apache.httpcomponents</groupId>
 8     <artifactId>httpmime</artifactId>
 9     <version>4.5.3</version>
10 </dependency>
查看代码

   2、编写客户端程序

 1 import java.io.BufferedReader;
 2 import java.io.File;
 3 import java.io.IOException;
 4 import java.io.InputStream;
 5 import java.io.InputStreamReader;
 6 import java.util.Arrays;
 7 
 8 import org.apache.commons.codec.binary.Base64;
 9 import org.apache.commons.lang3.StringUtils;
10 import org.apache.http.HttpEntity;
11 import org.apache.http.client.ClientProtocolException;
12 import org.apache.http.client.methods.CloseableHttpResponse;
13 import org.apache.http.client.methods.HttpPost;
14 import org.apache.http.entity.ContentType;
15 import org.apache.http.entity.mime.MultipartEntityBuilder;
16 import org.apache.http.entity.mime.content.ByteArrayBody;
17 import org.apache.http.entity.mime.content.FileBody;
18 import org.apache.http.entity.mime.content.StringBody;
19 import org.apache.http.impl.client.CloseableHttpClient;
20 import org.apache.http.impl.client.HttpClients;
21 import org.apache.http.util.EntityUtils;
22 
23 public class ClientUpload {
24 
25     public static void main(String[] args) throws ClientProtocolException, IOException, InterruptedException {
26         String url = "http://localhost:8090/plant/upload.action";
27 //        String basePath = "F:\\img\\";
28         String path = "G:\\123.jpg";
29         uploadImage(url, "dfsdfsdfsdf",path);
30     }
31 
32     public static String uploadImage(String path, String base64String, String imageFilePath) throws ClientProtocolException, IOException {
33         // 1. 创建上传需要的元素类型
34         // 1.1 装载本地上传图片的文件
35         File imageFile = new File(imageFilePath);
36         FileBody imageFileBody = new FileBody(imageFile);
37         // 1.2 装载经过base64编码的图片的数据
38 //        String imageBase64Data = base64String;
39 //        ByteArrayBody byteArrayBody = null;
40 //        if (StringUtils.isNotEmpty(imageBase64Data)) {
41 //            byte[] byteImage = Base64.decodeBase64(imageBase64Data);
42 //            byteArrayBody = new ByteArrayBody(byteImage, "image_name");
43 //        }
44         // 1.3 装载上传字符串的对象
45         StringBody name = new StringBody("admin", ContentType.TEXT_PLAIN);
46         // 2. 将所有需要上传元素打包成HttpEntity对象
47 //        HttpEntity reqEntity = MultipartEntityBuilder.create().addPart("name", name).addPart("img", imageFileBody).addPart("file2", byteArrayBody).build();
48         HttpEntity reqEntity = MultipartEntityBuilder.create().addPart("name", name).addPart("img", imageFileBody).build();
49         // 3. 创建HttpPost对象,用于包含信息发送post消息
50         HttpPost httpPost = new HttpPost(path);
51         httpPost.setEntity(reqEntity);
52         // 4. 创建HttpClient对象,传入httpPost执行发送网络请求的动作
53         CloseableHttpClient httpClient = HttpClients.createDefault();
54         CloseableHttpResponse response = httpClient.execute(httpPost);
55         // 5. 获取返回的实体内容对象并解析内容
56         HttpEntity resultEntity = response.getEntity();
57         String responseMessage = "";
58         try {
59             if (resultEntity != null) {
60                 InputStream is = resultEntity.getContent();
61                 BufferedReader br = new BufferedReader(new InputStreamReader(is));
62                 StringBuffer sb = new StringBuffer();
63                 String line = "";
64                 while ((line = br.readLine()) != null) {
65                     sb.append(line);
66                 }
67                 responseMessage = sb.toString();
68                 System.out.println("响应内容为:" + responseMessage);
69             }
70             EntityUtils.consume(resultEntity);
71         } finally {
72             if (null != response) {
73                 response.close();
74             }
75         }
76         return responseMessage;
77     }
78 }
查看代码

  3、到此为止,不出意外的话因该能够在控制台看到令人激动的“SUCCESS”输出

五、业务逻辑的优化完善

  1、由于图片是在不断生成的,所以要将图片不断地上传,并且保证上传地图片不重复。

 1 public static void main(String[] args) throws ClientProtocolException, IOException, InterruptedException {
 2     String url = "http://localhost:8090/plant/upload.action";
 3     String basePath = "F:\\img\\";
 4 //    String path = "G:\\123.jpg";
 5 //    uploadImage(url, "dfsdfsdfsdf",path);
 6     while (true) {
 7         File file = new File(basePath);
 8         String[] list = file.list();
 9         Arrays.sort(list);
10         for (String str : list) {
11             // 图片未标记为上传
12             if (!str.startsWith("Upload")) {
13                 uploadImage(url, "chao", basePath + str); // 上传图片
14                 new File(basePath + str).renameTo(new File(basePath + "Upload_" + str));    // 重命名图片
15             }
16         }
17         Thread.sleep(1000*60);    //等待60秒
18     }
19 }
查看代码

  2、服务端的完善

  图片如果想要能够在开发的网站中浏览到,一般业务比较小的话是直接传至Tomcat服务器,然后将路径记录并写入数据库;业务比较庞大的可以现在本地搭建图片服务器,采用Nginx或其他技术都是可以做到的,然后也需要将该路径写入数据库进行保存。

posted @ 2019-11-04 00:23  Ethany  阅读(9050)  评论(0编辑  收藏  举报