spring mvc 文件上传

文件上传的各框架都基于servlet实现,本文章介绍常用的文件上传方式

有些指定临时存储了路径,有些不指定临时存储目录会在tmp中缓存,完了后会删除

1、servlet

html代码

<form action="/file/upload" method="post" enctype="multipart/form-data">
    选择文件:<input type="file" name="upload"><br>
    <input type="submit" valie="上传"/>
</form>

 

 WEB-INF/web.xml

<servlet>
    <servlet-name>FileUploadServlet</servlet-name>
    <servlet-class>com.example.FileUploadServlet</servlet-class>
</servlet>
<servlet-mapping>
    <servlet-name>FileUploadServlet</servlet-name>
    <url-pattern>/upload</url-pattern>
</servlet-mapping>

servlet

@WebServlet("/upload")
@MultipartConfig
public class FileUploadServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // 检查是否是multipart内容类型
        if (!ServletFileUpload.isMultipartContent(request)) {
            throw new IllegalArgumentException("表单必须包含enctype=multipart/form-data");
        }

        // 创建ServletFileUpload实例
        ServletFileUpload upload = new ServletFileUpload(new DiskFileItemFactory());

        try {
            // 解析请求,获取文件项
            List<FileItem> items = upload.parseRequest(request);
            for (FileItem item : items) {
                if (!item.isFormField()) {
                    // 处理上传的文件
                    String fileName = item.getName();
                    InputStream inputStream = item.getInputStream();
                    // 这里可以编写代码将文件保存到服务器
                }
            }
        } catch (FileUploadException e) {
            e.printStackTrace();
        }
    }
}


 

 

2、过滤器

过滤器的目的是拦截上传的文件,上传到指定的临时目录,然后servlet或controller通过request.getAttribute("filePath")拿到上传的文件

这样的好处统一处理上传,验证,存储,便于对原始上传文件留档分析

@Slf4j
public class UploadFilter extends OncePerRequestFilter implements Filter {
    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws IOException, ServletException {

        if (ServletFileUpload.isMultipartContent(request)) {
            FileItemFactory factory = new DiskFileItemFactory();
            ServletFileUpload upload = new ServletFileUpload(factory);

            List<FileItem> fileItemList = null;
            try {
                fileItemList = upload.parseRequest(request);
            }catch (FileUploadException e) {
                log.error("upload file get fileItemList failed {}", e.getMessage());
            }catch (Exception e){
                if (e.getMessage().contains("EOF")){
                    log.warn("上传文件失败,客户端主动或因超时被动断开");
                }
            }

            if (fileItemList != null) {
                log.debug("web 文件上传开始时间:{}", DateUtils.formatDate(new Date(), DateUtils.DATE_FORMATE_PATTERN));
                int i = 0;
                for (FileItem fi : fileItemList) {
                    if (fi.isFormField()) {
                        request.setAttribute(fi.getFieldName(), fi.getString());
                    } else {
                        if (StringUtils.isEmpty(fi.getName()) || (fi.getName().lastIndexOf(".") <= 0 || fi.getName().lastIndexOf(".") == (fi.getName().length() - 1))) {
                            request.setAttribute("uploadStatus", "0");
                            request.setAttribute("uploadMessage", "文件名称为空或格式不正确!");
                            break;
                        }
                        String sourceFileName = fi.getName();
                        String basePath = FileUtils.getTempFilePath(sourceFileName);
                        File file = FileUtils.getTempFile(basePath, sourceFileName);
                        try {
                            fi.write(file);
                            request.setAttribute("filePath", basePath + file.getName());
                            request.setAttribute("uploadStatus", "1");
                        }catch (IOException | ClassNotFoundException ee){
                            log.warn("上传文件失败,客户端主动或因超时被动断开");
                        } catch (Exception e) {
                            e.printStackTrace();
                            request.setAttribute("uploadStatus", "0");
                            request.setAttribute("uploadMessage", "上传文件失败!");
                            log.error("上传文件失败 fileName={}", sourceFileName,e);
                            break;
                        }
                        request.setAttribute("fileName" + String.valueOf(++i), sourceFileName);
                    }
                }
                log.debug("web 文件上传结束时间:{}", DateUtils.formatDate(new Date(), DateUtils.DATE_FORMATE_PATTERN));
            }
        }

        filterChain.doFilter(request, response);
    }
}

3、commons-fileupload包

pom引包

<!-- https://mvnrepository.com/artifact/commons-fileupload/commons-fileupload -->
<dependency>
    <groupId>commons-fileupload</groupId>
    <artifactId>commons-fileupload</artifactId>
    <version>1.3.1</version>
</dependency>
<!-- https://mvnrepository.com/artifact/commons-io/commons-io -->
<dependency>
    <groupId>commons-io</groupId>
    <artifactId>commons-io</artifactId>
    <version>2.4</version>
</dependency>

html代码

<form action="/file/upload" method="post" enctype="multipart/form-data">
    选择文件:<input type="file" name="upload"><br>
    <input type="submit" valie="上传"/>
</form>

配置解析器:上传文件的大小最大是10兆

<!--配置文件解析器-->
    <bean id="multipartResolver"
 class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
        <property name="maxInMemorySize" value="10485760"/>
    </bean>

 constroller代码

@Controller
@RequestMapping("/file")
public class FileController {
    //文件上传
    @RequestMapping("/upload")
    public String upload(HttpServletRequest request) throws Exception {
        //解析 request 对象,获取上传文件项
        DiskFileItemFactory factory=new DiskFileItemFactory();
        ServletFileUpload upload=new ServletFileUpload(factory);
       List<FileItem> items=upload.parseRequest(request);
       //遍历
        for(FileItem item:items)
        {
            //判断当前 item 是否是上传文件项,
            // 如果是,需要把文件存在路径下,否则需要额外处理
            if(item.isFormField())
            {
                //说明是普通表单项
            }
            else
            {
                 //需要获取到上传文件的名称
                String fileName=item.getName();
//把文件的名称设置为唯一值
String uid=UUID.randomUUID().toString().replace("-","");
               fileName=uid+"_"+fileName;
               
                //需要获取到上传文件的名称
                String fileName=item.getFieldName();
                //完成文件上传
                item.write(new File(path,fileName));
                //删除临时文件
                item.delete();
            }
        }
        return "success";
    }
}

4、json

function uploadFile(){
    // 获取选择的文件
    var file = this.files[0];
    // 创建FormData对象来发送文件
    // var formData = new FormData();
    //formData.append("file",file);
    const param ={
        funcNo:"91000000"
        type:"1",
        excel_file: file,
    };
    doRequest(param,function(data){
        console.log("上传文件接口");
        console.log(data);
    });
}

java代码

获取的文件被转成base64的字符串

public Result execute() throws Exception {
    Result result = new Result();
    result.setErr_no(0);
    Map map = this.getParamMap();
    /***接收页面入参***/
    String type = MapHelper.getString(map, "type");
    String excelFile = MapHelper.getString(map, "excel_file");
    try {
       List<String> list = readExcelData(excelFile);
       result.setResult(list);
    }catch ( FrameException fe){
       throw  fe;
    }catch (Exception ex){
       result.setErr_no(-99);
       result.setErr_info("系统错误");
       logger.error("文件上传异常 type={}",type, ex);
    }
    return result;
}


/**
     * @param base64Str 文件路径
     * @description: 读取excel数据
     * @return: List<String> 手机号列表
     * @author: luohh
     * @date: 2024/7/25 13:36
     */
    protected List<String> readExcelData(String base64Str) throws  Exception {
        List<String> list = new ArrayList<>();
        Workbook workbook = null;
        InputStream inputStream = null;
        try {
            inputStream = new ByteArrayInputStream(Base64Utils.decode(base64Str));
            //判断输入的流是否是2007以上版本,如果是则对应文件后缀应该是xlsx
            try{
                if (POIFSFileSystem.hasPOIFSHeader(inputStream)) {
                    workbook =  new HSSFWorkbook(inputStream);
                }else{
                    // WorkbookFactory可以通过文件流直接生成合适的Workbook(HSSFWorkbook/XSSFWorkbook)
                    workbook = WorkbookFactory.create(inputStream);
                }
            }catch (Exception e){
                //这里try是为了解决xls和xls在读取的时候可能会的错,兜底使用WorkbookFactory
                workbook = WorkbookFactory.create(inputStream);
            }

            Sheet sheet = workbook.getSheetAt(0);
            for (Row row : sheet) {
                if (row.getRowNum() == 0) {
                    //第一行为标题
                    continue;
                }
                for (Cell cell : row) {
                    if (cell.getColumnIndex() == 0) {
                        //第一列为序号
                        continue;
                    }
                    if (cell.getCellTypeEnum() == CellType.NUMERIC) {
                        list.add(cell.getNumericCellValue() + "");
                        continue;
                    }
                    list.add(cell.getStringCellValue());
                }
            }
        }catch(InvalidFormatException xe){
            logger.error("文件格式错误",xe);
            throw new FrameException("文件格式错误!", 2);
        } catch(OLE2NotOfficeXmlFileException xe){
            logger.error("文件格式错误",xe);
            throw new FrameException("文件格式错误!", 2);
        } finally {
            if (null != inputStream) {
                try {
                    inputStream.close();
                } catch (Exception ex) {
                    logger.error("关闭workbook异常 " , ex);
                }
            }
            if (null != workbook) {
                try {
                    workbook.close();
                } catch (Exception ex) {
                    logger.error("关闭workbook异常 " , ex);
                }
            }
        }
        return list;
    }

  • 3
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值