入职java已经快2个月了。做了一个多月的改bug,6天的开发,刚做完一个文件上传,得好好整理下。

文件上传的大体思路其实是一样的,前端通过表单的方式上传,后端解析这个表单请求中的内容,得到文件部分的字段,再以流的形式读到内存中,后面怎么处理看业务了,比如保存到服务器等等。

一、前端
对于我这种前端ui等比较差的,果断选择了bootstrap为我撑撑场面。不会的可以搜一搜学一学,挺好用的。就是为你提供一些漂亮的样式,排版,自适应以及一些比较方便的插件。比如这个文件上传,基于bootstrap刚好有一个方便的fileinput。

先来秀一下效果

是不是挺漂亮的,实际上没有多少是靠我自己写的。

1)首先准备环境,你得有bootstrap环境,它依赖于jquery,这个你也是要的,有网络的童鞋可以直接使用cdn,没有的可以自行下载

<!-- 新 Bootstrap 核心 CSS 文件 -->
<link
    href="https://cdn.bootcss.com/bootstrap/3.3.7/css/bootstrap.min.css"rel="stylesheet">
<scriptsrc="https://cdn.bootcss.com/bootstrap/3.3.7/css/bootstrap-theme.min.css"></script>
<script src="https://cdn.bootcss.com/jquery/2.1.1/jquery.min.js"></script>
<scriptsrc="https://cdn.bootcss.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>

接着是file input插件的环境,我是下载下来用的,下载地址为https://github.com/kartik-v/bootstrap-fileinput/archive/v4.4.3.zip
只需要两个文件,大家对号入座

<script src="XXXXXXXXX/fileinput.min.js"></script><link
    href="XXXXXXXXXX/fileinput.min.css"rel="stylesheet">

2)使用,外面那个遮罩和框使用的是bootstrap的模态框,这里不介绍了。只说中间文件上传部分。

<input id="uploadfile" type="file" class="file file-loading">

没了,简介明了,你只要声明好它的class就好,多简单。

然后你在javascript中可以对它进行定制,比如我的需求是这样的:

//上传组件初始化$("#uploadfile").fileinput({language: 'zh', //设置语言uploadUrl: "${ctx}/dataModel/uploadModel", //上传的地址allowedFileExtensions: ['doc','docx'],//接收的文件后缀uploadAsync: true, //默认异步上传showUpload: true, //是否显示上传按钮showRemove : true, //显示移除按钮showPreview : true, //是否显示预览showCaption: true,//是否显示标题browseClass: "btn btn-primary", //按钮样式     dropZoneEnabled: false,//是否显示拖拽区域maxFileCount: 1, //表示允许同时上传的最大文件个数enctype: 'multipart/form-data',validateInitialCount:true,uploadExtraData: function(previewId, index) {   //额外参数var obj = {};obj.modelId = select.id;return obj;}});

同时上传完毕的回调

//异步上传返回结果处理$("#uploadfile").on("fileuploaded", function (event, data, previewId, index) {var response = data.response;//....});

前端到此结束

二、后端
后端你可以使用多种方式,我这使用的是SpringMVC,所以我的处理过程是写在Controller中的。

/*** 上传模型*/@RequestMapping(value = "/uploadModel",method = RequestMethod.POST)@ResponseBodypublic Object uploadModel(HttpServletRequest request,HttpServletResponse response){
//      String dataPortalDir = request.getRealPath("");    //dataPortal路径String dataPortalDir = "/Users/cd/Downloads/dataPortalSt";    //dataPortal路径String cacheDir = "/files/cache";String htmlDir = "/files/html";Map<String, Object> json = new HashMap<String, Object>();ShiroHttpServletRequest shiroRequest = (ShiroHttpServletRequest) request;//转换为multipartrequestCommonsMultipartResolver commonsMultipartResolver = new CommonsMultipartResolver();  MultipartHttpServletRequest multipartRequest = commonsMultipartResolver.resolveMultipart((HttpServletRequest) shiroRequest.getRequest());  /** 页面控件的文件流* */MultipartFile multipartFile = null;Map map =multipartRequest.getFileMap();for (Iterator i = map.keySet().iterator(); i.hasNext();) {Object obj = i.next();multipartFile=(MultipartFile) map.get(obj);}//获取额外参数String modelId =  multipartRequest.getParameter("modelId");/** 获取文件的后缀* */String filename = multipartFile.getOriginalFilename();//拷贝文件InputStream inputStream;String htmlUrl = "";try {inputStream = multipartFile.getInputStream();String tmpFilePath = dataPortalDir+cacheDir+File.separator+UUIDUtil.getUUID()+filename.substring(filename.lastIndexOf("."));//保存到服务器tmpFilePath = FileUtil.copyInputStreamToFile(inputStream, tmpFilePath,false);System.out.println("copy file to:"+tmpFilePath);} catch (Exception e) {e.printStackTrace();}json.put("code", 0);json.put("message", "上传成功");json.put("result", htmlUrl);return json;}

这里有点小问题,就是一开始拿到的request并不是MultipartHttpServletRequest,而是ShiroHttpServletRequest。做了一次转换之后才可以。

第二个问题是额外参数,通过转换后是存放在MultipartHttpServletRequest的multiParam…中的,在后端获取的时候通过MultipartHttpServletRequest的getParameter(“modelId”);直接拿到。- -这个折腾了我一下午

2017.09.18
今天发现这个后台上传貌似还有点问题在里面,我们的request被搭框架的整了下,不再是ShiroHttpServletRequest,此时强转会发生错误。这里经过改写后的方法为:

    @ResponseBody@RequestMapping(value = "upload")public DataResult<?> uploadFile(@RequestParam("file_data") MultipartFile uploadfile, @RequestParam("modelId") String modelId) {//....可以发现参数直接拿到MultipartFile和modelId}

2017.09.20
今天发现file input在i.e.上兼容性不大好。ie9上都会出问题。没辙了,只能改写。改写过程中发现request不再是MultipartHttpServletRequest,有点泪奔,这是肿么了。
发现了一篇介绍的,看着挺完善的

SpringMVC默认是关闭fileupload功能的,开启该能够并验证文件上传,需要做如下几件事情:
第一:打开SpringMVC的文件上传功能:
***-servlet.xml中配置:
<bean id="multipartResolver"class="org.springframework.web.multipart.commons.CommonsMultipartResolver"><property name="maxUploadSize" value="100000"/><property name="maxInMemorySize" value="10240" />
</bean>
配置后,当SpringMVC接受到multipartRequest的时候,就会把HttpServletRequest转为MultipartHttpServletRequest类型,
第二步:创建上传文件的file.jsp:
<form action="dynamicFields.action?method=uploadFile" method="post" enctype="multipart/form-data"><input type="file" name="myfile" id="myfile" value="" /><br/><input type="submit" value="确认提交"></form>
一定不要漏掉enctype="multipart/form-data",否则web容器认为这不是一个MultipartRequest请求,会报错org.springframework.web.multipart.MultipartException: The current request is not a multipart request。
第三步:Controller层创建代码:
@RequestMapping(params = {"method=uploadFile"})
public ModelAndView uploadFile(@RequestParam("myfile") MultipartFile myfile,HttpServletRequest request, HttpServletResponse response) throws Exception {if(!myfile.isEmpty()){logger.info(myfile.getName());byte[] bs= myfile.getBytes() ;logger.info(new String(bs));}return null;
}
部署web应用运行后,能够看到控制台中打印出上传文件的内容,BINGO搞定(SpringMVC依赖common-fileupload.jar,需要加载该jar包)

按理说应该是这样没跑了,可是我的还是有问题,明天继续改改看。request的类型变化真的好神奇- -。

2017.09.21上午
今天发现按照上面是对的。只不过这样是表单提交,表单提交会导致上传之后会发生页面跳转。禁止页面跳转的方式试了很多,网上说的那些都不大行,原因是他们是禁止了submit,相当于。这时候是不能上传的,要重新写上传。
经过多次查找资料,最后发现了一个好用的jquery-form,确实好用,官网http://malsup.com/jquery/form/.可以兼容到ie8,它的example中还提供了fileupload的例子http://malsup.com/jquery/form/progress.html。
用法很简单,几个回调清晰明了,如下:

$('form').ajaxForm({beforeSend: function() {var percentVal = '0%';bar.width(percentVal)percent.html(percentVal);},uploadProgress: function(event, position, total, percentComplete) {var percentVal = percentComplete + '%';bar.width(percentVal)percent.html(percentVal);},success: function() {var percentVal = '100%';bar.width(percentVal)percent.html(percentVal);},complete: function(xhr) {}}); 

这样就完成了对ie9的兼容,当然上传界面只能自己写写了。

2017.09.21下午
发现这个上传里面的坑还不少。今天上传一个文档的时候出来这么一个异常:

org.springframework.web.multipart.MultipartException: Could not parse multipart servlet request;
nested exception is java.io.IOException:
org.apache.tomcat.util.http.fileupload.FileUploadBase$IOFileUploadException: Processing of multipart/form-data request failed.
/upload_760aac73_045e_4c42_8f13_c36ad1041276_00000015.tmp (Permission denied)] with root cause
java.io.FileNotFoundException: /upload_760aac73_045e_4c42_8f13_c36ad1041276_00000015.tmp (Permission denied)

可以看出分成了两个tmp,目测是由于文件超过定义好的2M大小时,会被分成多块上传,上面两个则是分成的两个缓存文件。这个时候怎么处理?

经过多番查证这个问题是这样的,

参考1:http://blog.csdn.net/just4you/article/details/70233133
从Spring3.1开始,Spring提供了CommonsMultipartResolver
和StandardServletMultipartResolver处理multipart请求。

参考2:http://blog.csdn.net/hanger_liu/article/details/51970784
该文中使用CommonsMultipartResolver处理multipart请求,出现了跟我一样的问题。配置中的maxInMemorySIze 是文件上传的时候写到内存中的最大值,默认是10240字节,如果这里写大了,那么小于这个参数的文件则不会创建临时文件。

而我们使用了StandardServletMultipartResolver,以此类推在配置文件web.xml中

<multipart-config><location>/</location><max-file-size>20848820</max-file-size><max-request-size>418018841</max-request-size><file-size-threshold>1048576</file-size-threshold></multipart-config>

由于这里的file-size-threshold是1M左右,当我的文件大于这个阀值,就会保存到临时文件upload_xxx.tmp中,而这个文件是存放在location中的。所以解决办法出来了,增大阀值必然是可以的,不过不是根本办法。根本解决办法是location配置到有权限的文件夹中。dalao支了一招,直接去掉location配置,使用默认的location就没有权限问题了。

2017.09.22凌晨
今天上班的时候碰到一个奇葩问题,关于表单提交的,以前好好的一个可以用的项目,突然在表单提交的时候后台取不到参数值了。entype采用的是默认的,如果采用multipart编码就可以拿到。由于很多地方都是这样的,没法一个个加,特别有的还是用ajax,jquery的load等方式。
终于在2点多的时候解决了。环境问题- -,全部换成现在用的javase-1.8就好了。无语,睡觉了。

java前后台开发之文件上传相关推荐

  1. 微信小程序开发之文件上传下载应用场景(附Demo源码)

    微信小程序开发之文件上传下载应用场景(附Demo源码),Demo为小相册应用,源码在附件中,本示例需要腾讯云支持. http://www.henkuai.com/forum.php?mod=viewt ...

  2. java利用dropzone多文件上传

    DropzoneJS是一个提供文件拖拽上传并且提供图片预览的开源类库, 它是轻量级的,不依赖任何其他类库(如JQuery)并且高度可定制.文档官网https://www.dropzonejs.com/ ...

  3. 陪玩网站源码的PHP后台开发,文件上传与下载的实现

    在陪玩网站源码开发中,除了客户端之外还得开发一个服务端,而服务端一般采用的是PHP开发框架及语言,在服务端中我们会上传一些需要用到的文件,具体需要如何实现呢?今天我们就一起来了解一下陪玩网站源码的PH ...

  4. 转 [JAVA] 使用 common-fileupload 实现文件上传

    就在前段时间,还在苦于找到不到合适的上传组件,虽然很早就知道了 common-fileupload,但当时却因为没有找到如何获取表单参数的方法而使用 jspSmartUpload,历尽艰辛终于找到了它 ...

  5. spring boot 整合web开发之文件上传、静态资源访问、异常处理、返回JSON数据

    目录 springboot 整合web开发 返回json数据 静态资源访问 文件上传 全局异常 1.返回json数据 springboot默认的是jackson-databind做为json处理器.也 ...

  6. 04springMVC结构,mvc模式,spring-mvc流程,spring-mvc的第一个例子,三种handlerMapping,几种控制器,springmvc基于注解的开发,文件上传,拦截器,s

     1. Spring-mvc介绍 1.1市面上流行的框架 Struts2(比较多) Springmvc(比较多而且属于上升的趋势) Struts1(即将被淘汰) 其他 1.2  spring-mv ...

  7. java是怎么实现文件上传的_java怎么实现大文件上传

    Q1:javaWeb能和ftp实现大文件上传吗 java上传可以使用common-fileupload上传组件的.common-fileupload是jakarta项目组开发的一个功能很强大的上传文件 ...

  8. java基于servlet的文件上传

    研究了一天终于将java上传文件看懂了,当然懂的仅仅是皮毛,不妨记下来防止以后忘了. 我们在网上看关于文件的上传有很多的介绍,当然有的可以使用有的则不合适:我们首先来看前台的界面 <!DOCTY ...

  9. java 断点续传组件_chunkupload 文件上传断点续传组件(java) - 正式发布

    chunkupload简介 chunkupload是一款基于java语言的断点续传组件,针对文件上传,非文件下载,集成方便,使用简单. chunkupload实现如下功能: ·  实现断点续传 ·  ...

最新文章

  1. python socket编程
  2. clientHeight , scrollHeight , offsetHeight之间的区别及兼容方案
  3. 【Linux 操作系统】阿里云服务器 操作实战 部署C语言开发环境(vim配置,gcc) 部署J2EE网站(jdk,tomcat)
  4. 程序架构--BS,CS
  5. Spring Boot文件上传示例
  6. 中小企业上云多地域办公组网(SAG)解决方案
  7. 今天我的生日,纪念一下
  8. 网络规划设计师的参考资料和复习书籍
  9. Java programer的成长之路
  10. 华为交换机端口限速配置说明
  11. 线程生命周期(状态)
  12. nurbs曲线拟合程序_一种基于NURBS的空间自由曲线拟合方法与流程
  13. 怎么理解“付费搜索广告应当与自然搜索结果明显区分”
  14. excel中文件格式与扩展名对应关系
  15. Vulkan 多线程渲染
  16. phpstorm+xdebug远程调试
  17. eclipse 是用来写客户端的,MyEclipse 是用来写服务器端的,谐音记忆法,My 买,买服务器这样就好记了。
  18. 【天光学术】学前教育论文:幼儿园区角活动中存在的问题及有效对策(节选)
  19. Kali使用apt-cache search搜索想要的软件包
  20. 这些优秀的 Spring Cloud 开源软件,你知道的有几个?

热门文章

  1. 瑞星2005升级问题汇总
  2. how2j离线资源,2018,12月26最新
  3. 一文了解SCI论文投稿全流程
  4. activiti流程图查看
  5. windows安装vcpkg过程下载失败问题的解决方法
  6. 重复文件太多,该怎样快速清理?
  7. 蒋涛:TUP,分享产品背后的技术和用户体验
  8. 如何在达梦数据库安装ODBC
  9. 一个成功软件测试项目的经验(转载)
  10. MYSQL JDBC图书管理系统