SpringMVC服务+Android端OKHttp文件上传

最近尝试使用OKHttp替代Volley作为网络请求框架,这肯定是要对OKHttp进行重新封装的,所有封装完毕,就想对网络请求功能进行测试,基本的GET,POST验证通过了,但是在测试文件上传的时候遇到了门槛,需要自己搭建后台服务器来对此进行支持,这里记录一下这个过程,一方面对此做一次总结,同时也为后面使用OkHTTP上传文件监听进度回调做准备;还有就是希望能够帮助到同样有这个需求的朋友们。

一.SpringMVC服务器构建

1.后台服务器环境搭建

这边我并不想花太多的篇幅来讲解这一个过程(我能说我对后台也不太了解嘛?这些步骤纯碎百度),只是简单的讲一下思路.

  1. 首先需要做的就是配置JAVA开发环境,这个做Android开发的肯定提前都配置好了,没什么好多说的。

  2. 其次需要搭建一个tomcat服务器,我们只需要从官网现在一个tomcat压缩包,解压,配置一下TOMCAT_HOME等环境变量就行,可参考(http://jingyan.baidu.com/article/8065f87fcc0f182330249841.html),这边我用的是Tomcat8.0版本。

  3. 下载SpringMVC相关的库,目前Spring Framework官网都是给出的通过Maven,Gradle等构建工具使用Spring,我们没必要再去搭Maven,Gradle(当然,你有足够的兴趣跟经历,也可以尝试一下,我比较懒,哈哈),我们可以手动下载SpringFramework,我这边使用的是spring-framework-4.3.6,下载地址:http://repo.spring.io/release/org/springframework/spring/4.3.6.RELEASE/,此处,我一共引入了如下jar

SpringMVC服务+Android端OKHttp文件上传_第1张图片
SpringMVC需要的jar.png
  1. 下载一个Eclipse,对其添加tomcat服务器设置,window->Preferences->Server->Runtime Environment,

    按照下图的步骤,后台的开发环境基本就配置完成了。

SpringMVC服务+Android端OKHttp文件上传_第2张图片
eclipse配置tomcat.png
  1. 启动tomcat服务,打开浏览器,输入http://localhost:8080如果看到tomcat首页,说明tomcat服务器配置成功。
2.服务器代码构建
  1. 首先我们打开Eclipse,创建一个Dynamic Web Project,
SpringMVC服务+Android端OKHttp文件上传_第3张图片
创建动态web项目.png
  1. 这边我们先看一下最终的项目结构
SpringMVC服务+Android端OKHttp文件上传_第4张图片
服务器工程目录结构.png
  1. 下面看下对应的代码
    FileModel.java

    public class FileModel {
     private MultipartFile file;
    
        public MultipartFile getFile() {
           return file;
        }
    
        public void setFile(MultipartFile file) {
           this.file = file;
        }
    }
    

    FileUploadController.java

    @Controller
    public class FileUploadController {
    
     @Autowired
        ServletContext context; 
    
        @RequestMapping(value = "/fileUploadPage", method = RequestMethod.GET)
        public ModelAndView fileUploadPage() {
           FileModel file = new FileModel();
           ModelAndView modelAndView = new ModelAndView("fileUpload", "command", file);
           return modelAndView;
        }
    
        @RequestMapping(value="/fileUploadPage", method = RequestMethod.POST)
        public String fileUpload(@Validated FileModel file, BindingResult result, ModelMap model) throws IOException {
           if (result.hasErrors()) {
              System.out.println("validation errors");
              return "fileUploadPage";
           } else {            
              System.out.println("Fetching file");
              MultipartFile multipartFile = file.getFile();
              String uploadPath = context.getContextPath() + File.separator + "temp" + File.separator;
              //Now do something with file...
              File saveFile = new File(uploadPath+file.getFile().getOriginalFilename());
              System.out.println("File save path:" + saveFile.getAbsolutePath());
              FileCopyUtils.copy(file.getFile().getBytes(), saveFile);
              String fileName = multipartFile.getOriginalFilename();
              model.addAttribute("fileName", fileName);
              return "success";
           }
        }
    }
    

    fileUpload.js

    <%@ page contentType="text/html; charset=UTF-8"%>
    <%@ taglib prefix="form" uri="http://www.springframework.org/tags/form"%>
    
    
    Spring MVC上传文件示例
    
    
        
          请选择一个文件上传 : 
          
            
        
    
    
    

    success.js

    <%@ page contentType="text/html; charset=UTF-8"%>
    <%@ taglib prefix="form" uri="http://www.springframework.org/tags/form"%>
    
    
    Spring MVC上传文件示例
    
    
        
          请选择一个文件上传 : 
          
            
        
    
    
    

    spring-servlet.xml

    
    
    
        
        
        
        
            
            
        
    
        
    
    

    web.xml

    
    
      HelloSpringMVC
      
      
            spring
            org.springframework.web.servlet.DispatcherServlet
            
            1
       
      
      
            spring
            /
        
      
      
        index.html
        index.htm 
        index.jsp
        default.html
        default.htm
        default.jsp
      
    
    
  2. 以上代码配置完成后,将我们创建的工程添加到tomcat容器中,然后启动tomcat,打开浏览器输入http://localhost:8080/webapp/fileUploadPage,可以看到我们的fileUpload页面。webapp根据自己创建的Dynamic Web Project时的设置而定,我创建Dynamic Web Project时设置了Context root为webapp,默认为工程名字;fileUploadPage是Controller中RequestMapping注解中设置的内容。页面如下,至此,服务器端配置完全结束,我们也可以用一下,文件上传成功会跳转到success.jsp

SpringMVC服务+Android端OKHttp文件上传_第5张图片
服务器上传文件页面.png

二.Android使用okhttp实现文件上传

android端如何使用okhttp进行网络请求,这边不做介绍了,大家可以自定搜索了解一下,相信大多数人都是知道的,毕竟现在okhttp这么火。其实使用okhttp进行文件上传,也很简单,跟不同的网络请求用法没有多大的区别,无非就是再RequestBody中指定了上传的文件而已。在查看代码之前,我想在这边讲一下不同post请求的区别。

  1. 普通post请求

    我们都知道我们是无法在正常情况下看到post请求的请求参数的,post请求协议规定需要将post请求的请求参数放在http请求头的下面,且两者之间有一个空行隔开,普通的http post请求,请求参数都为基本数据类型,发送请求时,将这些数据通过key=value键值对的方式拼接成字符串,我们可以通过抓包工具看一下

SpringMVC服务+Android端OKHttp文件上传_第6张图片
抓包_post_基本数据.png
  1. 单一文件post请求

    根据上面的,我们可以发现,如果是上传单一文件也一样,只是http请求头后面的不是键值对,而是我们上传到文件的二进制形式。okhttp中需要使用RequestBody.create(媒体类型,文件)方法,封装请求body,请求格式如下,数据并没有截取完全。

SpringMVC服务+Android端OKHttp文件上传_第7张图片
抓包_post_单一文件.png
  1. 复合数据post请求

    这边我们需要考虑还有一种情况,复合数据的post请求,即post请求既有文件,又有键值对,甚至还有其他数据类型的时候,这个时候的post请求body就跟前两者有所区别了,如下,可以发现,它会将每一个请求数据进行分离,并记录每一个字段的信息,如key,value,内容长度,数据流类型等

    --fb12146e-52e3-4b7b-9345-6768dbcad759
    Content-Disposition: form-data; name="file"; filename="xxx.jar"
    Content-Type: application/octet-stream
    Content-Length: 208700
    
    [[二进制文件数据]]
    --fb12146e-52e3-4b7b-9345-6768dbcad759
    Content-Disposition: form-data; name="username"
    Content-Length: 13
    
    name_for_test
    --fb12146e-52e3-4b7b-9345-6768dbcad759
    Content-Disposition: form-data; name="password"
    Content-Length: 12
    
    pwd_for_test
    --fb12146e-52e3-4b7b-9345-6768dbcad759--
    

    OKHttp中将这种情况封装到了MultipartBody中,看了上面的格式,就不难理解MultipartBody中的addPart方法了

    new MultipartBody.Builder()
      .addPart(Headers.of(
                "Content-Disposition",
                "form-data; name=\"file\"; filename=\"xxx.jar\"")
                    , fileBody);
    //等价于下面这行代码
    new MultipartBody.Builder()
      .addFormDataPart("params","xxx.jar",fileBody);
    

讲了上面的知识,下面看一下Andorid端的上传代码,其实很简单,file为我们需要上传的文件,这边不要忘记启动tomcat,同时修改url的值。

RequestBody filebody = RequestBody.create(MediaType.parse("application/octet-stream"), file);
        RequestBody body = new MultipartBody.Builder()
                .addFormDataPart("file", file.getName(), filebody)
                .build();
        Request request = new Request.Builder()
                .url("http://192.168.1.106:8080/webapp/fileUploadPage")
                .post(body)
                .build();

        Call call = okHttpClient.newCall(request);
        call.enqueue(new Callback() {
            @Override
            public void onFailure(Call call, IOException e) {
                Log.e(TAG, "请求失败:" + e.getMessage());
            }

            @Override
            public void onResponse(Call call, Response response) throws IOException {
                Log.e(TAG, "请求成功!");
            }
        });

发送请求后,我们可以在Logcat中看到“请求成功!”的字样,说明请求成了,同时在Eclipse的console中可以看到服务器输出

请求成功.png

最后我们可以根据日志中显示的路径,去指定目录下查看对应的文件。

这篇文章就写到这里,最后祝大家国庆快乐!_

你可能感兴趣的:(SpringMVC服务+Android端OKHttp文件上传)