SpringMVC的文件上传

SpringMVC的文件上传

本篇文章主要解决两个问题

  • 怎么使用springMVC 框架上传文件
  • 怎么在服务器上的指定路径保存文件,是它成为一个小型的文件服务

1.文件的上传

1.1 上传文件需要的组件

  • SpringMVC 框架
  • form-components.js组件

1.2 HTML页面的实现

我们以一个form的表单为例,在这个表单中除了上传文件的选项外,还有其他的input选项,当点击提交按钮的时候,这些都会被提交到后台进行处理。下面是html的代码:

<form class="form-horizontal" id="add-blog-form" name="add-blog-form" enctype="multipart/form-data">
 <div class="control-group">
      <label class="control-label">博客名</label>
         <div class="controls">
             <input type="text" placeholder="请输入博客名" class="m-wrap medium" name="add-blogName">
             <span class="help-inline"></span>
         </div>
 </div>
<div class="control-group" >
    <label class="control-label">博客上传</label>
         <div class="controls">
            <input type="file"  placeholder=""  class="m-wrap medium" name="add-blog">
            <span class="help-inline"></span>
         </div>
 </div>
<div class="control-group" >
     <label class="control-label">图片上传</label>
         <div class="controls">
             <input type="file"  placeholder=""  class="m-wrap medium" name="add-fig">
             <span class="help-inline"></span>
         </div>
 </div>
 </form>

注意: form 标签中必须要有这句enctype="multipart/form-data .在这个html中,还需引入form-components.js :

<script src="../js/jquery-form.js" ></script>

1.3 javaScript 的实现

jQuery Form插件是一个优秀的Ajax表单插件,可以非常容易地、无侵入地升级HTML表单以支持Ajax。我们使用它的ajaxSubmit()方法来提交表单。代码如下:

$("#add-blog-form").ajaxSubmit({
                    dataType: 'json',
                    url: '../blog/upload.do',
                    type: 'POST',
                    contentType: "application/x-www-form-urlencoded; charset=utf-8",
                    success:function(data){
                            $("#add-responsive").modal('hide');
                            var r ;
                            console.log("su"+data)
                            if(data=="success"){

                                r = "添加成功!";
                                showRow();
                            }else{
                                r = "添加失败!";
                            }
                            $("h2#all-result").html(r);
                            $("#result-responsive").modal('show');
                        },
                    error:function(){
                    //输出错误信息
                    } 

1.4 后台的处理

首先配置spring-mvc 的xml文件如下:

<!-- 配置文件上传,如果没有使用文件上传可以不用配置,当然如果不配,那么配置文件中也不必引入上传组件包 -->
       <bean id="multipartResolver"
             class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
              <!-- 默认编码 -->
              <property name="defaultEncoding" value="utf-8" />
              <!-- 文件大小最大值 -->
              <property name="maxUploadSize" value="10485760000" />
              <!-- 内存中的最大值 -->
              <property name="maxInMemorySize" value="40960" />
       </bean>

后台使用的是SpringMVC 来进行处理,代码如下:

@Value("#{configProperties['mdFile.path']}")
    private String mdFilePath;
@Value("#{configProperties['imgFile.path']}")
    private String imgFilePath;
@RequestMapping(value="/upload" ,method = RequestMethod.POST, produces = "application/json;charset=utf8")
@ResponseBody
public String upload(@RequestParam(value="add-blog") MultipartFile file1,@RequestParam(value="add-fig", required=false) MultipartFile file2,
@RequestParam(value="add-blogName") String blogName ) throws IOException {
    if (!file1.isEmpty()) {
        InputStream in1 = null;
        OutputStream out1 = null;
        String imgRealPath=null;
        try {
                // 获得在tomcat中项目的路径, 需要在web.xml配置ft.webapp
                //String webRootPath = System.getProperty("ft.webapp");
                String html = null;
                //logger.info(webRootPath);
                // String rootPath = System.getProperty("catalina.home");
                //File dir = new File(webRootPath + File.separator + "uploadFiles");
                File dirMd = new File(mdFilePath+blogName);
                if (!dirMd.exists())
                    dirMd.mkdirs();
                File serverFile = new File(dirMd.getAbsolutePath() + File.separator + file1.getOriginalFilename());
                in1 = file1.getInputStream();
                out1 = new FileOutputStream(serverFile);
                byte[] b = new byte[1024];
                int len = 0;
                while ((len = in1.read(b)) > 0) {
                    html += new String(b,0,len,"UTF-8");
                    out1.write(b, 0, len);
                }
                out1.close();
                in1.close();
                if(file2!=null){
                    InputStream inImg = null;
                    OutputStream outImg = null;
                    try {
                        File dirImg = new File(imgFilePath+blogName);
                        if (!dirImg.exists())
                            dirImg.mkdirs();
                        imgRealPath = dirImg.getAbsolutePath() + File.separator + file2.getOriginalFilename();
                        File serverFileImg = new File(imgRealPath);
                        inImg = file2.getInputStream();
                        outImg = new FileOutputStream(serverFileImg);
                        byte[] b2 = new byte[1024];
                        int len2 = 0;
                        while ((len2 = inImg.read(b2)) > 0) {
                            outImg.write(b2, 0, len2);
                        }
                        outImg.close();
                        inImg.close();
                    }catch (Exception e){
                        return "fail";
                    }finally {
                        if (outImg != null) {
                            outImg.close();
                            outImg = null;
                        }

                        if (inImg != null) {
                            inImg.close();
                            inImg = null;
                        }
                    }
                }
                html = blogService.renderToHtml(html);
                System.out.println("++++++++++++"+html);
                String noNeed = "<p>null</p>";
                String newHtml="";
                if(html.startsWith(noNeed)){
                    newHtml = html.replaceFirst(noNeed," ");
                }
                System.out.println("=========="+newHtml);
        
                //insert form to database
                blogService.insertBlog2database(blogName,  newHtml,  imgRealPath);
                //update tags info
                tagService.updateTagofBlogId(blogName);
                return "success";

            } catch (Exception e) {

                return "fail";
            } finally {
                if (out1 != null) {
                    out1.close();
                    out1 = null;
                }

                if (in1 != null) {
                    in1.close();
                    in1 = null;
                }
            }
        } else {

            return null;
        }
    }

上面代码最主要的是对接收的文件进行按字节流的读入和写出,关于写出文件的相关问题会在下面章节进行详细的介绍。其他的是一些业务的逻辑代码,可以跳过。

2. 上传后文件的处理

在前一节中,我们通过前端处理把要上传的文件信息传到了后端,并在后端写入的指定的路径,一般来说上传的文件都会在tomcat的工程路径下,但是这样有一定的局限性,比如我们读取文件又要写一些读入的代码,做一些判断。因此,我们会使用Tomcat做一个简单的文件服务器,这样只需要在数据库中存储文件的路径,然后使用代码访问这个路径就可以访问到文件了。

2.1 Tomcat 的相关配置

server.xml中的Host标签中加入Context标签的内容 , 如下所示:

<Host name="localhost"  appBase="webapps"
            unpackWARs="true" autoDeploy="true">

        <!-- SingleSignOn valve, share authentication between web applications
             Documentation at: /docs/config/valve.html -->
        <!--
        <Valve className="org.apache.catalina.authenticator.SingleSignOn" />
        -->

        <!-- Access log processes all example.
             Documentation at: /docs/config/valve.html
             Note: The pattern used is equivalent to using pattern="common" -->
        <Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs"
             prefix="localhost_access_log." suffix=".txt"
             pattern="%h %l %u %t "%r" %s %b" />
        <Context path="/root/blogfile" docBase="/root/blogfile" />
</Host>

注: 使用的是Tomcat8.0版本,这里实际上配置的是虚拟目录,<Context>是Host标记的子元素,表示一个虚拟目录,它主要有两个属性,path就相当于虚拟目录名字,而 docbase则是具体的文件位置。这样设置后就可以访问到了,如果想在浏览器中看到文件还需要设置web.xml, 把listings设置为true

<servlet>
        <servlet-name>default</servlet-name>
        <servlet-class>org.apache.catalina.servlets.DefaultServlet</servlet-class>
        <init-param>
            <param-name>debug</param-name>
            <param-value>0</param-value>
        </init-param>
        <init-param>
            <param-name>listings</param-name>
            <param-value>true</param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet> ```
这样访问`host+路径`就可以访问到文件,如果不配置会出现404.

 ![uploadfile.png](http://upload-images.jianshu.io/upload_images/1814710-f221e7535f611499.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)

#### 2.2 后台的配置处理
在1.4 中,我们刚开始使用了@Value注解进行了配置:
``` java
@Value("#{configProperties['mdFile.path']}")
    private String mdFilePath;
@Value("#{configProperties['imgFile.path']}")
    private String imgFilePath;

它的作用是获取配置文件的key所对应的值,我们知道,在java中一些变化的量,尤其是路径,最好写在配置文件中,这样发生变化只修改配置文件就可以了,不用动代码。我们的配置文件如下:文件名:filePath.properties内容:

mdFile.path = /root/blogfile/md
imgFile.path = /root/blogfile/fig

文件名:applicationContext.xml追加内容:

<bean id="configProperties" class="org.springframework.beans.factory.config.PropertiesFactoryBean">
        <property name="locations">
            <list>
                <value>classpath:filePath.properties</value>
            </list>
        </property>
</bean>
<bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PreferencesPlaceholderConfigurer">
        <property name="properties" ref="configProperties"/>
</bean>

至此,SpringMVC的上传文件以及后期的处理已经完成。

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

推荐阅读更多精彩内容

  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,633评论 18 139
  • 一. Java基础部分.................................................
    wy_sure阅读 3,805评论 0 11
  • ¥开启¥ 【iAPP实现进入界面执行逐一显】 〖2017-08-25 15:22:14〗 《//首先开一个线程,因...
    小菜c阅读 6,373评论 0 17
  • apache下的httpclient工具可大大简化开发过程中的点对点通信,本人将以微信多媒体接口为例,展示http...
    划破的天空阅读 5,272评论 0 32
  • 目前高校没有产品经理的对口专业,更谈不上成体系的培养。应届生进入公司后,直接上岗就成为了一名救火员。少有公司会提供...
    曹顺达阅读 730评论 1 9