Seasons123 / blog-FE

web前端相关issue is my blog :lollipop:
2 stars 0 forks source link

Ajax不能提交附件的原因以及解决方法 #82

Open Seasons123 opened 5 years ago

Seasons123 commented 5 years ago

一、原因 Ajax是基于JavaScript的,而js出于安全考虑是不能操作文件的,所以Ajax不能直接上传附件,可以用其他变通方式实现。 但是Ajax提交也是基于HTTP协议的,它也分GET和POST提交方式,可以把表单内容放到消息体中,这和Form.submit()是一样的,为什么用form.submit()就可以处理附件,而Ajax就不可以呢? 用js获取内容肯定存在权限问题 ,js出于安全考虑是不能操作文件的。用表单的input控件来提交文件时 获取客户端内容是浏览器负责的,而不是js来负责。一个是浏览器负责读取本地文件,一个是开发者写的 JS读取本地文件,出于安全考虑,后者显然没有权限。 二、解决 附件的上传和下载和后台交互的时候不能用ajax,一般会使用form,走form表单提交的形式和后台交互 实现上传和下载,但是,直接这种form.submit()与后台交互的方式,无法取到后台传来的值(errorCode)。解决方法:使用$.post(url,data, function() {}),在function中拿到后台返回的errorCode 值,如果该值为0,再给出表单提交操作并给出前台提示信息。 1

【附】后台方法-附件下载

 @RequestMapping(value = "/downloadAttach.do", method = { RequestMethod.POST })
  @ResponseBody
  public void download(HttpServletRequest request, HttpServletResponse response) {
    Map<String, Object> map = new HashMap<String, Object>();
    String attachId = request.getParameter("attach_id");
    Map fileData = attachmentService.getFileById(attachId);
    if (fileData.get("errorCode").equals("0")) {
      String isTempFile = fileData.get("isTempFile").toString();
      String filePath = fileData.get("localPath").toString();
      String fileName = fileData.get("fileName").toString();
      String uploadMode = fileData.get("uploadMode").toString();

   //   if(!uploadMode.equals(FAST_DFS_MODE)){
          File file = new File(filePath);
          OutputStream out = null;
          InputStream in = null;
          try {
            out = response.getOutputStream();
            fileName = URLEncoder.encode(fileName, "UTF-8");// 转码,很重要
            // 设置文件名
            response.addHeader("Content-Disposition", "attachment;filename=" + fileName);
            response.setContentType("application/octet-stream");
            response.setCharacterEncoding("UTF-8");

            in = new FileInputStream(file);
            byte[] b = new byte[2048];
            int size = in.read(b);
            while (size != -1) {
              out.write(b, 0, size);
              size = in.read(b);
            }
            map.put("errorCode", "0");
            System.out.println(map);
          } catch (Exception e) {
            map.put("errorCode", "-1");
            map.put("errorMsg", "文件输出到客户端异常");
          } finally {
            try {
              if (null != in) {
                in.close();
              }
              if (null != out) {
                out.close();
              }
              if (isTempFile.equals("1")) {
                file.delete();//删除临时文件
              }
            } catch (IOException e) {
              map.put("errorCode", "-1");
              map.put("errorMsg", "文件流关闭异常");
            }
          }
    } else {
      map = fileData;
    }
//    return map;
  }
Seasons123 commented 5 years ago

前端涉及方法点: preventDefault方法:取消事件的默认动作。语法event.preventDefault()。说明,该方法将通知 Web 浏览 器不要执行与事件关联的默认动作(如果存在这样的动作)。例如,如果 type 属性是 "submit",在事件 传播的任意阶段可以调用任意的事件句柄,通过调用该方法,可以阻止提交表单。注意,如果 Event 对象 的 cancelable 属性是 fasle,那么就没有默认动作,或者不能阻止默认动作。无论哪种情况,调用该方法都 没有作用。

post方法:通过HTTP POS请求从服务器载入数据。$.post()是jquery一个简单的 POST 请求功能以取代复 杂$.ajax . 语法:jQuery.post(url,data,success(data, textStatus, jqXHR),dataType)