图片上传(学习1)单图

  项目开发不可避免的要用到图片上传,最近也上网看了一些插件的引用,不过都不是很明白.而且感觉(...有点小尴尬).所以就决定从最简单的实现开始,慢慢的自己封装功能.这样自己完善起来也方便,并且自我感觉,对于后台开发来讲(当然,现在的主要还是写交互),自己写这种上传组件的过程,也是一种学习的过程.和自我提升的过程.

  1.先介绍下所使用的框架,后台controller是用的springboot,mybatis框架,前端交互则是用的thymeleaf.页面则是HTML,这里不对thymeleaf做太多介绍(毕竟本人也是刚接触).

  2. 纯form表单的提交,当然,这种表单提交的方式有很大的漏洞,因为这种上传的方式是读取的input标签的选取的文件内容,对于需要重复选择/做移除的需求,这种表单提交的方式将会显得非常的局限.因为表单提交的图片是input标签最近拉取的文件列表.对于上一次拉取的图片,即便是在HTML中实现了纯前端的预览,可是实际的效果是无法实现的.

    当然,对于单图上传来说,这种方式还是可以适用的,只是无法对所上传的图片做额外的处理,比如:在上传的时候自动为图片加水印.(当然,听说是有后台/服务器实现的方法,这还有待研究)

  代码如下:

    

前端HTML
<
form th:action="@{表单提交对应的后台路径}"method="post" th:object="${对应的后台表单对象}" enctype="multipart/form-data" > <input class="file" name="pictures" type="file" style="display:none;" multiple accept="image/*" onchange="imagePreview(this)"/>
    <!-->input标签的name属性是很关键的,因为后台controller获取数据流就是通过这个name属性获取的<-->
    
<!-->multiple是声明可选择多图,单图的情况下可去掉 accept="image/*"是声明只可选取图片类型 <-->

</form>
预览JS

  function imagePreview(input){
    var files = input.files;//获取input标签所选择的图片集合

    var html ="";
    for (var i = 0; i < files.length; i++) {
      var file = files[i];
      var reader = new FileReader();
      reader.onload = function(e) {
      for( var j=0;j<$(".img .fileimg").length;j++) {
      // console.log($(".img .fileimg").eq(j).find("img").attr("src"));通过这种方式可获取到已有的图片SRC
        if( e.target.result == $(".img .fileimg").eq(j).find("img").attr("src")){//if方法判断图片是否已经选取,可避免重复选择
          return false;
        }
      }

      //加入没有重复选择通过fileReader对象即可读取图片的二进制数据,实现预览
      html ="<div class='fileimg'><em class='remove'>移除</em><img width='100' height='100' id='pic"+j+"' src='"+e.target.result+"'></div>"
      $(".img").append(html);//页面中做回显
      };
      reader.readAsDataURL(file);//把图片读取为URL数据
    }
  }

  后台对应的映射controller

  

  @RequestMapping("/admin/resource/projectEdit")
  @Controller
  @MultipartConfig
  public class ProjectEditController extends AbstractController{   

    @RequestMapping(value = "updateOrAddProject" , method = RequestMethod.POST)
    public String updateOrAddProject(@RequestParam(value = "pictures") MultipartFile [] pictures) {

        //@RequestParam(value = "pictures")中的pictures就是对应的页面中的name="pictures",而此时读取的数据实际上为最近一次通过input标签拉取的图片数据

`    }

  }

  对应上传图片的方法,这里我给写到service层了

  public List<Long> addPiture(MultipartFile[] pictures) {
    List<Long> newPictureIds = new ArrayList<Long>();
    for (MultipartFile picture : pictures) {

      /** 获取图片大小判断是否有真的图片上传,因为在几遍不选择图片的情况下,后台的图片数组中length属性也为1 */
      Long picSize = picture.getSize();
      if(picSize != null && picSize > 0) {
        /** 获取图片类型 */
        String contentType1 = picture.getContentType();
        String pictureType = contentType1.split("/")[1].toString();
        /** 图片保存名称 */
        String pictureName = System.currentTimeMillis() + "." +pictureType;
        /** 获取上传日期 */
        String nowDate = DateUtil.dateToString(new Date() , "yyyyMMdd");
        /** 文件相对存放路径 */
        String uploadFloder = "/upload/" + accountId + "/" + nowDate + "/"+pictureName;
        /** 文件保存绝对路径 */
        String filePath = fileUploadFolder + accountId +"\\" + nowDate + "\\" + pictureName;
        /** 图片所在文件夹路径 */
        String picFolderPath = fileUploadFolder + accountId +"\\" +nowDate +"\\" ;
        try {
          uploadPicture(picture.getBytes() , picFolderPath , pictureName);
        }catch (IOException e){
          throw new ServiceException("图片上传错误");
        }
      }else{
        continue;
      }
    }
return newPictureIds;
}

  具体执行图片流写入的方法:

  

  public void uploadPicture(byte[] file , String filePath , String fileName) {
    File picturePath = new File(filePath);
    if(!picturePath.exists()) {
      picturePath.mkdirs();
    }
    FileOutputStream out = null;
    try {
      out = new FileOutputStream(filePath+fileName);
      out.write(file);
      out.flush();
      out.close();
    }catch (IOException e) {
      throw new ServiceException("图片上传错误");
    }
}

 

 

  

posted @ 2017-12-06 00:46  每天学习1点点  阅读(392)  评论(0编辑  收藏  举报