有时候,在开发中,需要遇到拖拽上传图片的需求,即从磁盘选中一张或多张图片,然后按着鼠标把图片拖动到页面上指定的区域,实现图片的上传。

需要购买阿里云产品和服务的,点击此链接领取优惠券红包,优惠购买哦,领取后一个月内有效: https://promotion.aliyun.com/ntms/yunparter/invite.html?userCode=fp9ccf07

1、后端上传图片的接口

我是之前用vue写一个简单的后台系统的时候,用Java的SpringMVC+MyBatis的框架写了一个简单的后台管理的一些接口,刚好有一个上传用户头像的接口,该接口是把上传后的图片存储在另外一台Tomcat下,这里就直接使用这个接口来上传图片。

  1. /**
  2. * 上传用户头像
  3. * @param request
  4. * @param response
  5. */
  6. @ResponseBody
  7. @RequestMapping(value="uploadSysHeadImg.do", method=RequestMethod.POST)
  8. public void uploadSysHeadImg(HttpServletRequest request,HttpServletResponse response){
  9. JSONObject jo = new JSONObject();
  10. //校验token
  11. // boolean f = tokenService.checkToken(request, response);
  12. // if(!f){ return; }
  13.  
  14. try {
  15. MultipartResolver resolver = new CommonsMultipartResolver(request.getSession().getServletContext());
  16. MultipartHttpServletRequest Murequest = resolver.resolveMultipart(request);
  17. Map<String, MultipartFile> files = Murequest.getFileMap();//得到文件map对象
  18. // 实例化一个jersey
  19. Client client = new Client();
  20.  
  21. List<String> fileNameList = new ArrayList<>();
  22. List<String> relaPathList = new ArrayList<>();
  23. List<String> realPathList = new ArrayList<>();
  24. for(MultipartFile pic: files.values()){
  25. String uploadInfo = Upload.upload(client, pic, request, response, uploadHost, headImgPath);
  26. if(!"".equals(uploadInfo)){ //如果上传成功
  27. String[] infoList = uploadInfo.split(";");
  28. fileNameList.add(infoList[0]); //文件名
  29. relaPathList.add(infoList[1]); //相对路径
  30. realPathList.add(infoList[2]); //真实路径
  31. }else{ //如果上传失败
  32. fileNameList.add("");
  33. relaPathList.add("");
  34. realPathList.add("");
  35. }
  36. }
  37. jo.put("success", 1);
  38. jo.put("error", null);
  39. jo.put("fileNameList", fileNameList);
  40. jo.put("relaPathList", relaPathList);
  41. jo.put("realPathList", realPathList);
  42. }catch (Exception e) {
  43. jo.put("success", 0);
  44. jo.put("error", "上传失败");
  45. }
  46. ResponseUtils.renderJson(response, jo.toString());
  47. }

2、前端代码

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <meta name="viewport" content="width=device-width, initial-scale=1.0">
  6. <meta http-equiv="X-UA-Compatible" content="ie=edge">
  7. <title>Document</title>
  8. <script src="https://cdn.bootcss.com/jquery/1.12.0/jquery.js"></script>
  9. <style>
  10. #drop_area {
  11. position: relative;
  12. width: 300px;
  13. height: 150px;
  14. border: 1px dashed #ddd;
  15. border-radius: 5px;
  16. margin-bottom: 5px;
  17. }
  18. #drop_area .text {
  19. position: absolute;
  20. width: 100%;
  21. top: 60px;
  22. text-align: center;
  23. font-size: 14px;
  24. }
  25. #img_area {
  26. width: 300px;
  27. }
  28. #img_area img {
  29. width: 300px;
  30. margin-bottom: 5px;
  31. }
  32. </style>
  33. </head>
  34. <body>
  35. <div id="drop_area">
  36. <div class="text"><span>+</span><span>将文件拖到此处,即可上传</span></div>
  37. </div>
  38. <div id="img_area"></div>
  39. </body>
  40.  
  41. <script>
  42. var dp = document.getElementById('drop_area');
  43. dp.addEventListener('dragover', function(e) {
  44. e.stopPropagation();
  45. //阻止浏览器默认打开文件的操作
  46. e.preventDefault();
  47. e.dataTransfer.dropEffect = 'copy';
  48. });
  49.  
  50. //单图上传
  51. // dp.addEventListener("drop", function(e) {
  52. // e.stopPropagation();
  53. // //阻止浏览器默认打开文件的操作
  54. // e.preventDefault();
  55. // var files = e.dataTransfer.files;
  56. // var file = files[0];
  57. // var formData = new FormData();
  58. // formData.append("file", file);
  59. // $.ajax({
  60. // type: 'post',
  61. // url: 'http://127.0.0.1:8081/ssm_project/sysUser/uploadSysHeadImg.do',
  62. // data: formData,
  63. // contentType: false, //必须 禁止jQuery设置Content-Type请求头
  64. // processData: false, //必须 禁止jQuery处理发送的数据
  65. // dataType: "json",
  66. // success: function(res){
  67. // if(res.success == 1){
  68. // }
  69. // },
  70. // });
  71. // });
  72.  
  73. //多图上传
  74. dp.addEventListener("drop", function(e) {
  75. e.stopPropagation();
  76. //阻止浏览器默认打开文件的操作
  77. e.preventDefault();
  78. var files = e.dataTransfer.files;
  79. var formData = new FormData();
  80. for(var i =0; i<files.length; i++){
  81. formData.append("file"+i, files[i]);
  82. }
  83. $.ajax({
  84. type: 'post',
  85. url: 'http://127.0.0.1:8081/ssm_project/sysUser/uploadSysHeadImg.do',
  86. data: formData,
  87. contentType: false, //必须 禁止jQuery设置Content-Type请求头
  88. processData: false, //必须 禁止jQuery处理发送的数据
  89. dataType: "json",
  90. success: function(res){
  91. if(res.success == 1){
  92. res.realPathList.forEach(function(item){
  93. $('#img_area').append('<img src="'+item+'">');
  94. });
  95. }
  96. },
  97. });
  98. });
  99. </script>
  100. </html>

我在这里用的是jquery的ajax请求。

里面用的formData对象来上传图片的,该对象的作用是:

  1、用一些键值对来模拟一系列表单控件,即把form中所有表单元素的name与value组装成一个queryString;

  2、异步上传二进制文件

另外有两个属性的值,我们必须要设置它们的值为false:

  contentType: false, //必须 禁止jQuery设置Content-Type请求头

    processData: false, //必须 禁止jQuery处理发送的数据

其中先封装了一个 formData 对象,然后使用 post 方法将文件传给服务器。

这里我们就要先说说在 http 中传输文件的问题。起初http协议中没有上传文件方面的功能,直到rfc1867为http协议添加了这个功能。当然在rfc1867中限定form的method必须为POST, enctype = “multipart/form-data” 以及<input type = "file">

当我们使用表单上传文件时,我们来查看他的Request headers,如下图:

发现在 multipart/form-data 后面有boundary以及一串字符,这是分界符,后面的一堆字符串是随机生成的,目的是防止上传文件中出现分界符导致服务器无法正确识别文件起始位置。说到这肯定就要说说这分界符有啥作用呢?

因为对于上传文件,我们没有在使用原有的 http 协议,所以 multipart/form-data 请求是基于 http 原有的请求方式 post 而来的.那么来说说这个全新的请求方式与 post 的区别

  1. 请求头的不同,对于上传文件的请求,contentType = multipart/form-data是必须的,而 post 则不是,毕竟 post 又不是只上传文件~。

  2. 请求体不同。这里的不同也就是指前者在发送的每个字段内容之间必须要使用分界符来隔开,比如文件的内容和文本的内容就需要分隔开,不然服务器就没有办法正常的解析文件,而后者 post 当然就没有分界符直接以 name = "value"的形似发送。

而在我的这段JQuery ajax() 方法中,我设置了contentType = false,这不是冲突了吗?这当然没有,因为当我们查看这时的 Request headers,会发现还是有分界符。这是因为当我们在 form 标签中设置了enctype = “multipart/form-data”,这样请求中的 contentType 就会默认为 multipart/form-data (我用的是new formData()对象,它其实就是模拟了一个表单控件,也就是form标签)。而我们在 ajax 中 contentType 设置为 false 是为了避免 JQuery 对其操作,从而失去分界符,而使服务器不能正常解析文件。

3、效果

需要购买阿里云产品和服务的,可以点击此链接领取优惠券红包,优惠购买哦,领取后一个月内有效: https://promotion.aliyun.com/ntms/yunparter/invite.html?userCode=fp9ccf07

js拖拽上传图片的更多相关文章

  1. h5拖拽上传图片

    h5实现拖拽上传图片 本文将为大家介绍如何通过js实现拖拽上传图片. 首先我们要禁用调浏览器默认的拖拽事件: window.onload = function(){ //拖离 document.add ...

  2. HTML5 CSS3 经典案例:无插件拖拽上传图片 (支持预览与批量) (二)

    转载请标明出处:http://blog.csdn.net/lmj623565791/article/details/31513065 上一篇已经实现了这个项目的整体的HTML和CSS: HTML5 C ...

  3. 再谈React.js实现原生js拖拽效果

    前几天写的那个拖拽,自己留下的疑问...这次在热心博友的提示下又修正了一些小小的bug,也加了拖拽的边缘检测部分...就再聊聊拖拽吧 一.不要直接操作dom元素 react中使用了虚拟dom的概念,目 ...

  4. React.js实现原生js拖拽效果及思考

    一.起因&思路 不知不觉,已经好几天没写博客了...近来除了研究React,还做了公司官网... 一直想写一个原生js拖拽效果,又加上近来学react学得比较嗨.所以就用react来实现这个拖 ...

  5. js拖拽效果

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  6. 关于 JS 拖拽功能的冲突问题及解决方法

    前言 我在之前写过关于 JS 拖拽的文章,实现方式和网上能搜到的方法大致相同,别无二致,但是在一次偶然的测试中发现,这种绑定事件的方式可能会和其它的拖拽事件产生冲突,由此产生了对于事件绑定的思考.本文 ...

  7. js拖拽分析

    js拖拽分析 思路 1.三个鼠标事件,mousedown,mousemove,mouseup 2.可移动性absolute 3.边界限制 得到鼠标点击处和div边界的距离,然后得出top 和 left ...

  8. JS拖拽div(移动)

    <!doctype html><html><head> <meta charset="utf-8"> <title>JS ...

  9. 浅谈js拖拽

    本文来自网易云社区 作者:刘凌阳 前言 本文依据半年前本人的分享<浅谈js拖拽>撰写,算是一篇迟到的文章. 基本思路 虽然现在关于拖拽的组件库到处都是,HTML5也把拖放纳入了标准.但考虑 ...

随机推荐

  1. NetCore 获取appsetting.json 文件中的配置

    1. using Microsoft.Extensions.Configuration public class HomeController : Controller { public IConfi ...

  2. xtrabackup 全量备份、恢复数据

    1.全量备份 [root@localhost lib]##innobackupex --defaults-file=$defaults_file --user=$mysql_username --pa ...

  3. 无法在<fastCGI>应用程序配置中找到<handler> scriptProcessor

    在打开php文件的时候发现iis7.5报错了 每次在切换php版本的时候不知道为什么会出现这个错误,有的时候就又不会报错直接可以正常使用,然而php版本确定已经下载好,才可能的打开这个页面,那么就是i ...

  4. python爬虫常用正则表达式组合匹配

    ["\']匹配什么?(.*?)匹配什么? ["\']       -----------     匹配单双引号 (.*?)xxx ----------- 匹配任意长度字符+xxx ...

  5. linux svn 中文 https://my.oschina.net/VASKS/blog/659236

    https://my.oschina.net/VASKS/blog/659236 设置服务器: export LC_ALL=zh_CN.UTF-8长久之计, echo export LC_ALL=zh ...

  6. 网页判断浏览器是否安装flash

    <script> //检验flash版本 以及falsh是否安装 function detectFlash() { try { if(navigator.mimeTypes.length& ...

  7. 了解使用wireshark抓包工具

    一.简介 1.什么是wireshark 百度: Wireshark(前称Ethereal)是一个网络封包分析软件.网络封包分析软件的功能是撷取网络封包,并尽可能显示出最为详细的网络封包资料.Wires ...

  8. [leetcode ]429. N-ary Tree Level Order Traversale (easy)

    原题 思路: bfs,每一层遍历一次加到一个vector,同时把该点的子元素加到queue中. class Solution { public: vector<vector<int> ...

  9. MyEclipse2014破解版

    百度云:链接:http://pan.baidu.com/s/1c3jKMa 密码:yss0 等版本)后,不要打开软件. 二.解压破解文件压缩包,得到一下文件列表: 三.双击run.bat,即可运行cr ...

  10. Java中注释的使用

    Java 中注释有三种类型:单行注释.多行注释.文档注释 我们可以通过 javadoc 命令从文档注释(/**aa*/)中提取内容,生成程序的 API 帮助文档. 打开首页,查看下生成的 API 文档 ...