前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Java 单文件、多文件上传 / 实现上传进度条

Java 单文件、多文件上传 / 实现上传进度条

原创
作者头像
Krry
修改2019-08-13 14:34:58
6.6K0
修改2019-08-13 14:34:58
举报
文章被收录于专栏:KrryblogKrryblog

博客地址:https://ainyi.com/76

日常,工作

在这里总结一下上传吧(是以前做过的练习,就汇总到个人博客吧)

java ssm 框架实现文件上传

实现:单文件上传、多文件上传(单选和多选),并且用 ajax 异步刷新,在当前界面显示上传的文件

后端

首先 springmvc 的配置文件要配置上传文件解析器:

代码语言:txt
复制
<!-- 配置文件解析器 -->
<bean id="multipartResolver"
      class="org.springframework.web.multipart.commons.CommonsMultipartResolver"
      p:defaultEncoding="utf-8">
  <property name="uploadTempDir" value="/temp"></property>
  <property name="maxUploadSize">
    <value>209715200</value><!-- 200MB -->
  </property>
  <property name="maxInMemorySize">
    <value>4096</value><!-- 4KB大小读写 -->
  </property>
</bean>

其次在 pom.xml 中要配置上传文件的依赖

代码语言:txt
复制
<dependency>
  <groupId>commons-io</groupId>
  <artifactId>commons-io</artifactId>
  <version>2.4</version>
</dependency>

<dependency>
  <groupId>commons-fileupload</groupId>
  <artifactId>commons-fileupload</artifactId>
  <version>1.3.1</version>
</dependency>

<dependency>
  <groupId>org.apache.commons</groupId>
  <artifactId>commons-lang3</artifactId>
  <version>3.3.2</version>
</dependency>

单文件上传

代码语言:txt
复制
/**
 * 单文件上传
 * @param file
 * @param request
 * @return
 * @throws IllegalStateException
 * @throws IOException
 * @throws JSONException
 */
public static String simUpload(MultipartFile file, HttpServletRequest request) 
        throws IllegalStateException, IOException, JSONException{
    
    if(!file.isEmpty()){
        String path = request.getSession().getServletContext().getRealPath("/upload");
        //定义文件
        File parent = new File(path);
        if(!parent.exists()) parent.mkdirs();
        
        HashMap<String, Object> map = new HashMap<String,Object>();
        
        String oldName = file.getOriginalFilename();
        
        long size = file.getSize();
        
        //使用TmFileUtil文件上传工具获取文件的各种信息
        //优化文件大小
        String sizeString = TmFileUtil.countFileSize(size);
        //获取文件后缀名
        String ext = TmFileUtil.getExtNoPoint(oldName);
        //随机重命名,10位时间字符串
        String newFileName = TmFileUtil.generateFileName(oldName, 10, "yyyyMMddHHmmss");
        
        String url = "upload/"+newFileName;
        
        //文件传输,parent文件
        file.transferTo(new File(parent, newFileName));
        
        map.put("oldname",oldName);//文件原名称
        map.put("ext",ext);
        map.put("size",sizeString);
        map.put("name",newFileName);//文件新名称
        map.put("url",url);
        
        //以json方式输出到页面
        return JSONUtil.serialize(map);
    }else{
        return null;
    }
}

多文件上传(整合了==单选文件==和==多选文件==的两种)

代码语言:txt
复制
/**
 * 多文件上传
 * @param files
 * @param request
 * @return
 * @throws IllegalStateException
 * @throws IOException
 * @throws JSONException
 */
public static List<HashMap<String, Object>> mutlUpload(MultipartFile[] files, HttpServletRequest request) 
        throws IllegalStateException, IOException, JSONException{
    
    if(files.length > 0){
        String path = request.getSession().getServletContext().getRealPath("/upload");
        //定义文件
        File parent = new File(path);
        if(!parent.exists()) parent.mkdirs();
        
        //创建这个集合保存所有文件的信息
        List<HashMap<String, Object>> listMap = new ArrayList<HashMap<String, Object>>();
        
        //循环多次上传多个文件
        for (MultipartFile file : files) {
            
            //创建map对象保存每一个文件的信息
            HashMap<String, Object> map = new HashMap<String,Object>();
            
            String oldName = file.getOriginalFilename();

            long size = file.getSize();
            
            //使用TmFileUtil文件上传工具获取文件的各种信息
            //优化文件大小
            String sizeString = TmFileUtil.countFileSize(size);
            //获取文件后缀名
            String ext = TmFileUtil.getExtNoPoint(oldName);
            //随机重命名,10位时间字符串
            String newFileName = TmFileUtil.generateFileName(oldName, 10, "yyyyMMddHHmmss");
            
            String url = "upload/"+newFileName;
            
            //文件传输,parent文件
            file.transferTo(new File(parent, newFileName));
            
            map.put("oldname",oldName);//文件原名称
            map.put("ext",ext);
            map.put("size",sizeString);
            map.put("name",newFileName);//文件新名称
            map.put("url",url);
            
            listMap.add(map);
        }
        
        //以json方式输出到页面
        return listMap;
    }else{
        return null;
    }
}

前端

前端代码:

文件多选,实际上在

代码语言:txt
复制
<input type="file" 
       name="fileupmulti"
       accept="image/jpeg,image/png"
       onchange="mutiFiles(this)"
       multiple/>

多加了一个 multiple 属性

onchange 事件代码

代码语言:txt
复制
// 单文件上传
function uploadFile(obj){
  // 创建一个 FormData 对象,用一些键值对来模拟一系列表单控件
  // 即把 form 中所有表单元素的 name 与 value 组装成一个 queryString
  let form = new FormData();
  let fileObj = obj.files[0];
  form.append('doc',fileObj);
  
  // ajax 代码...
}

// 多文件上传(多选)
function mutiFiles(obj){
  let form = new FormData();
  let fileObj = obj.files;
  let length = fileObj.length;
  // 将 fileObj 转换成数组
  // let filese = Array.from(fileObj);
  for(let i = 0; i < length; i++){
    form.append('doc', fileObj[i]);
  }

  // ajax 代码...
}

// 多文件上传(单选:一个一个选择文件,最后点击提交按钮触发的方法)
function multipartone(){
  let file1 = $('.fileupon11').get(0).files[0];
  let file2 = $('.fileupon12').get(0).files[0];
  let file3 = $('.fileupon13').get(0).files[0];
  //如果都是空,则直接退出
  isEmpty(file1) && isEmpty(file2) && isEmpty(file3) return;
        
  let form = new FormData();
  //用同一个名字,注入到controller层的参数数组
  form.append('doc', file1);
  form.append('doc', file2);
  form.append('doc', file3);
  
  // ajax 代码...
}

要想在当前界面显示上传的文件,而不跳转,就利用 ajax 异步请求

不过需要注意的是,我这里使用 FormData() 储存文件对象, ajax 要配上这几个参数才可实现文件上传:

代码语言:txt
复制
$.ajax({
 type: "post",
 data: form,  // FormData()对象
  url: basePath+"/upload/mutl",
 contentType: false, // 必须false才会自动加上正确的Content-Type
 processData: false, // 必须false才会避开 jQuery 对 formdata 的默认处理, XMLHttpRequest会对 formdata 进行正确的处理
 success: function(data){
    // TODO
 }
})

controller 层调用

代码语言:txt
复制
package com.krry.controller;

import java.io.IOException;
import java.util.HashMap;
import java.util.List;

import javax.servlet.http.HttpServletRequest;

import org.apache.struts2.json.JSONException;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.multipart.MultipartFile;

import com.krry.util.UploadUtil;

/**
 * 文件上传类
 * KrryUploadController
 * @author krry
 * @version 1.0.0
 *
 */
@Controller
@RequestMapping("/upload")
public class KrryUploadController {
    
    /**
     * 单文件上传
     * @param file
     * @param request
     * @return
     * @throws IllegalStateException
     * @throws IOException
     * @throws JSONException
     */
    @ResponseBody
    @RequestMapping(value = "/file")
    public String krryupload(@RequestParam("doc") MultipartFile file, HttpServletRequest request) throws IllegalStateException, IOException, JSONException{

        //调用工具类完成上传,返回相关数据到页面
        return UploadUtil.simUpload(file, request);
    }
    
    /**
     * 多文件上传
     * @param file
     * @param request
     * @return
     * @throws IllegalStateException
     * @throws IOException
     * @throws JSONException
     */
  // 这里的MultipartFile[] file表示前端页面上传过来的多个文件,file对应页面中多个file类型的input标签的name,但框架只会将一个文件封装进一个MultipartFile对象,
  // 并不会将多个文件封装进一个MultipartFile[]数组,直接使用会报[Lorg.springframework.web.multipart.MultipartFile;.<init>()错误,
  // 所以需要用@RequestParam校正参数(参数名与MultipartFile对象名一致),当然也可以这么写:@RequestParam("file") MultipartFile[] files。
    @ResponseBody
    @RequestMapping(value = "/mutl")
    public List<HashMap<String, Object>> krryuploadMutl(@RequestParam("doc") MultipartFile[] file, HttpServletRequest request) throws IllegalStateException, IOException, JSONException{
        //调用工具类完成上传,返回相关数据到页面
        return UploadUtil.mutlUpload(file, request);
    }
}

进度条

要显示上传进度条,我这里采用原生 ajax 方法

代码语言:txt
复制
function uploadFile(obj) {
  // ...
  // 一些获取上传对象的相关代码

  // 创建一个 ajax 对象
  var xhr = new XMLHttpRequest();

  // 规定请求的类型、URL 以及是否异步处理请求。true为异步
  // 请求是异步的。因为要实时获取到上传的进度,则请求需是异步的,如果是同步的话,会直到请求完成才能获取到响应
  xhr.open("post", basePath+"/upload/file", true);

  // 上传成功进入的回调函数
  xhr.onreadystatechange = function(){
  if(xhr.readyState==4 && xhr.status==200){ // 状态 4 和 200 代表和服务器端交互成功
    // 获取上传成功的返回数据
    var data = xhr.responseText.trim();
    jdata = eval("("+data+")");
    krry_uploadsuccess(jdata);
  }
  };
  // 监听文件上传的进度
  xhr.upload.addEventListener("progress", progressFunction, false);
  // 发送http请求:将请求发送到服务器,与后台交互
  xhr.send(form);
}


// 上传进度的回调函数
function progressFunction(event) {
  let prograssbarDom = document.getElementById("prograssbar");
  let fileRea = document.getElementById("fileRea");
  if (prograssbarDom && event.lengthComputable) {
    let percent = event.loaded / event.total; //文件上传进度百分比
    let p = Math.floor(percent*100);
    prograssbarDom.style.width = p+"%";
    fileRea.innerHTML = p+"%";
  }
}

附上优化文件大小的代码:

代码语言:txt
复制
/**
 * 将文件的字节数转换成文件的大小
 * com.krry.uitl 
 * 方法名:format
 * @author krry 
 * @param size
 * @return String
 * @exception 
 * @since  1.0.0
 */
public static String format(long size){
    float fsize = size;
    String fileSizeString;
    if (fsize < 1024) {
        fileSizeString = String.format("%.2f", fsize) + "B"; //2f表示保留两位小数
    } else if (fsize < 1048576) {
        fileSizeString = String.format("%.2f", fsize/1024) + "KB";
    } else if (fsize < 1073741824) {
        fileSizeString = String.format("%.2f", fsize/1024/1024) + "MB";
    } else if (fsize < 1024 * 1024 * 1024) {
        fileSizeString = String.format("%.2f", fsize/1024/1024/1024) + "GB";
    } else {
        fileSizeString = "0B";
    }
    return fileSizeString;
}

博客地址:https://ainyi.com/76

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 后端
  • 前端
  • 进度条
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档