`

Spring Boot文件上传示例(Ajax和REST)

 
阅读更多

本文介绍如何使用Ajax请求在Spring Boot Web应用程序(REST结构)中上传文件。

本文中使用的工具:

  • Spring Boot 1.4.3.RELEASE
  • Spring 4.3.5.RELEASE
  • Thymeleaf
  • jQuery (webjars)
  • Maven
  • Embedded Tomcat 8.5.6
  • Google Chrome浏览器

1. 项目结构

一个标准的Maven项目结构。如下图所示 -

2. 项目依赖

声明一个额外的jQuery webjar依赖关系,适用于HTML格式的Ajax请求。

文件:pom.xml
```xml
4.0.0

<groupId>com.yiibai</groupId>
<artifactId>spring-boot-file-upload</artifactId>
<packaging>jar</packaging>
<version>1.0</version>

<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>1.4.3.RELEASE</version>
</parent>

<properties>
    <java.version>1.8</java.version>
</properties>

<dependencies>

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-thymeleaf</artifactId>
    </dependency>

    <!-- hot swapping, disable cache for template, enable live reload -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-devtools</artifactId>
        <optional>true</optional>
    </dependency>

    <dependency>
        <groupId>org.webjars</groupId>
        <artifactId>jquery</artifactId>
        <version>2.2.4</version>
    </dependency>

</dependencies>

<build>
    <plugins>
        <!-- Package as an executable jar/war -->
        <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
        </plugin>
    </plugins>
</build>


## 3.文件上传
为了支持Ajax请求和响应,最简单的解决方案返回一个ResponseEntity。
以下示例演示了上传文件的三种可能方式:
1. 单文件上传 - `MultipartFile`
2. 多文件上传 - `MultipartFile []`
3. 将文件上传到模型 - `@ModelAttribute`

*文件:RestUploadController.java*

```java
package com.yiibai.controller;

import com.yiibai.model.UploadModel;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

@RestController
public class RestUploadController {

    private final Logger logger = LoggerFactory.getLogger(RestUploadController.class);

    //Save the uploaded file to this folder
    private static String UPLOADED_FOLDER = "D://temp//";

    //Single file upload
    @PostMapping("/api/upload")
    // If not @RestController, uncomment this
    //@ResponseBody
    public ResponseEntity<?> uploadFile(
            @RequestParam("file") MultipartFile uploadfile) {

        logger.debug("Single file upload!");

        if (uploadfile.isEmpty()) {
            return new ResponseEntity("please select a file!", HttpStatus.OK);
        }

        try {

            saveUploadedFiles(Arrays.asList(uploadfile));

        } catch (IOException e) {
            return new ResponseEntity<>(HttpStatus.BAD_REQUEST);
        }

        return new ResponseEntity("Successfully uploaded - " +
                uploadfile.getOriginalFilename(), new HttpHeaders(), HttpStatus.OK);

    }

    // Multiple file upload
    @PostMapping("/api/upload/multi")
    public ResponseEntity<?> uploadFileMulti(
            @RequestParam("extraField") String extraField,
            @RequestParam("files") MultipartFile[] uploadfiles) {

        logger.debug("Multiple file upload!");

        String uploadedFileName = Arrays.stream(uploadfiles).map(x -> x.getOriginalFilename())
                .filter(x -> !StringUtils.isEmpty(x)).collect(Collectors.joining(" , "));

        if (StringUtils.isEmpty(uploadedFileName)) {
            return new ResponseEntity("please select a file!", HttpStatus.OK);
        }

        try {

            saveUploadedFiles(Arrays.asList(uploadfiles));

        } catch (IOException e) {
            return new ResponseEntity<>(HttpStatus.BAD_REQUEST);
        }

        return new ResponseEntity("Successfully uploaded - "
                + uploadedFileName, HttpStatus.OK);

    }

    // maps html form to a Model
    @PostMapping("/api/upload/multi/model")
    public ResponseEntity<?> multiUploadFileModel(@ModelAttribute UploadModel model) {

        logger.debug("Multiple file upload! With UploadModel");

        try {

            saveUploadedFiles(Arrays.asList(model.getFiles()));

        } catch (IOException e) {
            return new ResponseEntity<>(HttpStatus.BAD_REQUEST);
        }

        return new ResponseEntity("Successfully uploaded!", HttpStatus.OK);

    }

    //save file
    private void saveUploadedFiles(List<MultipartFile> files) throws IOException {

        for (MultipartFile file : files) {

            if (file.isEmpty()) {
                continue; //next pls
            }

            byte[] bytes = file.getBytes();
            Path path = Paths.get(UPLOADED_FOLDER + file.getOriginalFilename());
            Files.write(path, bytes);

        }

    }
}

以上示例的简单模型 - @ModelAttribute文件:UploadModel.java -

package com.yiibai.model;

import org.springframework.web.multipart.MultipartFile;

import java.util.Arrays;

public class UploadModel {

    private String extraField;

    private MultipartFile[] files;

    public String getExtraField() {
        return extraField;
    }

    public void setExtraField(String extraField) {
        this.extraField = extraField;
    }

    public MultipartFile[] getFiles() {
        return files;
    }

    public void setFiles(MultipartFile[] files) {
        this.files = files;
    }

    @Override
    public String toString() {
        return "UploadModel{" +
                "extraField='" + extraField + '\'' +
                ", files=" + Arrays.toString(files) +
                '}';
    }
}

视图文件

多个文件上传的HTML表单。文件:upload.html -

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<body>

<h2>Spring Boot多文件上传示例(使用AJAX)</h2>

<form method="POST" enctype="multipart/form-data" id="fileUploadForm">
    <input type="text" name="extraField"/><br/><br/>
    <input type="file" name="files"/><br/><br/>
    <input type="file" name="files"/><br/><br/>
    <input type="submit" value="提交" id="btnSubmit"/>
</form>

<h1>Ajax提交结果:</h1>
<pre>
    <span id="result"></span>
</pre>

<script type="text/javascript" src="webjars/jquery/2.2.4/jquery.min.js"></script>
<script type="text/javascript" src="js/main.js"></script>

</body>
</html>
HTML

5. jQuery - Ajax请求

jQuery通过表单#id获取表单,并通过Ajax请求发送多部分(multipart)表单数据。文件:resources/static/js/main.js -

$(document).ready(function () {

    $("#btnSubmit").click(function (event) {

        //stop submit the form, we will post it manually.
        event.preventDefault();

        fire_ajax_submit();

    });

});

function fire_ajax_submit() {

    // Get form
    var form = $('#fileUploadForm')[0];

    var data = new FormData(form);

    data.append("CustomField", "This is some extra data, testing");

    $("#btnSubmit").prop("disabled", true);

    $.ajax({
        type: "POST",
        enctype: 'multipart/form-data',
        url: "/api/upload/multi",
        data: data,
        //http://api.jquery.com/jQuery.ajax/
        //http://developer.mozilla.org/en-US/docs/Web/API/FormData/Using_FormData_Objects
        processData: false, //prevent jQuery from automatically transforming the data into a query string
        contentType: false,
        cache: false,
        timeout: 600000,
        success: function (data) {

            $("#result").text(data);
            console.log("SUCCESS : ", data);
            $("#btnSubmit").prop("disabled", false);

        },
        error: function (e) {

            $("#result").text(e.responseText);
            console.log("ERROR : ", e);
            $("#btnSubmit").prop("disabled", false);

        }
    });

}
Js

6. 异常处理程序

要处理来自Ajax请求的异常,只需扩展ResponseEntityExceptionHandler并返回一个ResponseEntity。文件:RestGlobalExceptionHandler.java -

 

package com.yiibai.exception;

import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.multipart.MultipartException;
import org.springframework.web.servlet.mvc.method.annotation.ResponseEntityExceptionHandler;

import javax.servlet.http.HttpServletRequest;

//http://docs.spring.io/spring-boot/docs/current/reference/htmlsingle/#boot-features-error-handling
@ControllerAdvice
public class RestGlobalExceptionHandler extends ResponseEntityExceptionHandler {

    @ExceptionHandler(MultipartException.class)
    @ResponseBody
    ResponseEntity<?> handleControllerException(HttpServletRequest request, Throwable ex) {

        HttpStatus status = getStatus(request);

        return new ResponseEntity(new CustomError("0x000123", "Attachment size exceeds the allowable limit! (10MB)"), status);

        //return new ResponseEntity("Attachment size exceeds the allowable limit! (10MB)", status);

        // example
        //return new ResponseEntity(ex.getMessage(), status);
        //return new ResponseEntity("success", responseHeaders, HttpStatus.OK);

    }

    private HttpStatus getStatus(HttpServletRequest request) {
        Integer statusCode = (Integer) request.getAttribute("javax.servlet.error.status_code");
        if (statusCode == null) {
            return HttpStatus.INTERNAL_SERVER_ERROR;
        }
        return HttpStatus.valueOf(statusCode);
    }

}
Java

7. 运行演示

使用默认的嵌入式Tomcat的启动Spring Boot命令:mvn spring-boot:run.
访问:http://localhost:8080/ ,选择几个文件并单击提交以触发ajax请求。

提示:打开目录:F:/temp 应该能看到上传的文件。

 

本站代码下载:http://www.yiibai.com/siteinfo/download.html

 

 

http://www.yiibai.com/spring-boot/file-upload-example-ajax-and-rest.html

分享到:
评论

相关推荐

    vue+spring boot整合笔记和代码资料

    3. **前后端通信**:Vue.js使用axios或fetch等库进行Ajax请求,与Spring Boot提供的REST API进行交互。发送GET、POST、PUT、DELETE请求,获取或修改后端数据。 4. **安全认证**:在整合过程中,安全性是必须考虑的...

    demo-autocomplete:一个简单的spring boot autocomplete ajax rest

    【标题】"demo-autocomplete:一个简单的spring boot autocomplete ajax rest" 涉及到的关键技术是Spring Boot、Ajax以及RESTful API的实现,用于创建一个自动完成的功能。这个项目提供了一个基本的框架,展示了如何...

    spring-boot-ajax:如何使用Jquery和Ajax调用rest API

    通过以上步骤,你就可以在Spring Boot应用中使用Jquery和Ajax调用REST API了。这只是一个基础示例,实际应用中可能需要处理更多复杂情况,如分页、过滤、错误处理等。此外,还可以考虑使用Jquery的`$.getJSON()`、`$...

    SpringBootAjax:前端的Spring Boot Ajax示例

    在IT领域,Spring Boot是一个非常流行的Java框架,它简化...这涉及到前端JavaScript的Ajax调用、Spring Boot后端的REST API设计以及JSON数据的处理。对于Java开发者来说,掌握这些技能对构建现代、高效的应用至关重要。

    spring+vue的demo

    通过这个整合示例,你可以了解Spring Boot和Vue.js的基本整合流程,以及如何构建一个具备基本功能的Web应用。随着对两者深入理解,你可以逐步添加更复杂的功能,如分页、搜索、权限控制等,从而构建出更完善的业务...

    spring-crud:使用Spring Boot实现的REST API的实现

    综上所述,"spring-crud"项目是一个涵盖了Spring Boot、REST API设计、数据库操作、前端框架等多个关键点的示例,适合初学者了解和学习Web服务的开发流程。通过这个项目,开发者可以掌握Spring Boot应用的开发基础,...

    simple-crm-example:一个非常非常简单的 CRM 应用程序,使用 Java Spring Boot,JPA,使用 REST 架构构建。 一个简单的AJAX接口用于测试项目

    一个非常非常简单的 CRM 应用程序,使用 Java Spring Boot,JPA,使用 REST 架构构建。 一个简单的 AJAX 接口用于测试项目。 怎么跑 应用程序“fat”jar 位于目标文件夹内。 jar 包含运行应用程序所需的一切(嵌入式...

    spring-boot-datatables:Spring Data JPA扩展可与出色的jQuery插件DataTables(http

    弹簧启动数据表该项目是使用的示例Spring Boot项目怎么跑mvn clean spring-boot:run 然后打开特征Datahome是在文件home.js中定义的,具有用户类的列名称匹配属性: $(document).ready(function() {var table = $('...

    sample_spring_boot

    标题“sample_spring_boot”和描述中的相同内容表明这是一个关于Spring Boot的示例项目。Spring Boot是Java领域中一个流行的微服务框架,它简化了创建独立的、生产级别的基于Spring的应用程序。这个压缩包可能包含了...

    springboot-vue.zip

    标题“springboot-vue.zip”表明这是一个包含Spring Boot和Vue.js集成示例的压缩文件,适合初学者了解如何将这两个流行的技术框架结合使用。在这个项目中,你将学习到Spring Boot后端服务与Vue.js前端框架如何协同...

    my-catalogue:用angularjs的Spring Boot应用程序

    AngularJS利用$http服务发送AJAX请求到Spring Boot的REST API,获取或更新产品数据。Spring Boot通过Jackson库将Java对象序列化为JSON格式,方便前端解析。此外,为了保证安全性,可以考虑集成Spring Security,提供...

    springboot整合阿里云oss进行文件上传

    在本文中,我们将深入探讨如何将Spring Boot与阿里云OSS(Object Storage Service)集成,实现文件上传功能。阿里云OSS是一种云存储服务,它提供了高可用、高可靠的存储解决方案,适合各种业务场景下的文件存储。...

    详解Spring Boot实战之Restful API的构建

    - 通过Spring Boot实现Restful API,可以更好地支持前后端分离的开发模式,前端通过Ajax请求获取数据,后端通过RESTful API提供数据。 6. JSON数据格式: - JSON(JavaScript Object Notation)是一种轻量级的...

    springboottest2.rar

    在你提供的 "springboottest2.rar" 压缩包中,我们可以推测这是一个简单的 Spring Boot 示例项目,包含前端与后端交互、数据库操作、数据CRUD(创建、读取、更新、删除)、用户登录功能以及表单提交事件处理。...

    Springboot中ajax实现动态绑定省市区

    以上就是使用Spring Boot和Ajax动态绑定省市区数据的基本流程。在实际项目中,你可能需要考虑更多细节,如错误处理、缓存策略、数据格式转换等。同时,高德地图API的使用需要遵循其官方文档和使用条款,确保正确集成...

    Springboot+vue的毕业生实习与就业管理系统(有报告) Javaee项目,springboot vue前后端分离项目

    这个项目不仅是一个实际的应用示例,也是学习和掌握Spring Boot 和 Vue.js 技术的好材料。通过分析和实践,开发者可以深入了解前后端分离架构,提升自己的全栈开发能力。同时,对于毕业生来说,参与这样的项目有助于...

    springboot+vue+elementui实现增删改查和分页查询

    它整合了Spring Boot、Vue.js和Element UI,这三个组件分别在后端、前端和UI设计方面发挥关键作用,实现了基本的数据操作和展示功能。 首先,Spring Boot是Java生态系统中的一个框架,它简化了创建独立的、生产级别...

    SpringBoot+Echarts实例

    在本项目中,"SpringBoot+Echarts实例"是一个结合了Spring Boot框架和Echarts图表库的实战应用。这个项目旨在帮助开发者了解如何在Java后端使用Spring Boot处理数据,并通过前端Echarts展示丰富的可视化效果。下面...

    Spring MVC expert

    在本资源包中,"Spring MVC expert"很可能包含深入的Spring MVC教程、最佳实践和示例代码,帮助读者成为Spring MVC领域的专家。 1. **Spring MVC基本概念** - **模型(Model)**:存储业务逻辑和数据的部分,通常...

    基于SpringBoot + LayUI的后台管理系统.zip

    3. **自动配置(Auto Configuration)**:根据类路径中的jar文件和Spring配置,自动配置相应的Bean。 4. **命令行接口(CLI)**:用于快速原型开发和运行Spring Boot应用。 5. **健康检查与Actuator**:提供了监控和...

Global site tag (gtag.js) - Google Analytics