How to Implement Multi-Image Upload and Preview in Spring MVC

This guide walks through building a Spring MVC backend that accepts multiple image uploads, returns them for preview, and covers front‑end HTML, JavaScript handling, multipart configuration, and common pitfalls such as parameter naming, file size limits, and global exception handling.

Programmer DD
Programmer DD
Programmer DD
How to Implement Multi-Image Upload and Preview in Spring MVC

Recently a company needed a merchant registration backend where merchants can upload multiple pictures and see them displayed. This article records the key points for implementing that feature with Spring MVC.

Upload

The controller uses Spring MVC and receives the files via MultipartFile[]. The parameter name must match the name attribute of the <input> element.

@RequestMapping("/pic")
@ResponseBody
public ResponseEntity<String> pic(MultipartFile[] pictures) throws Exception {
    ResponseEntity<String> responseEntity = new ResponseEntity<>();
    long count = Arrays.asList(pictures).stream()
            .map(MultipartFile::getOriginalFilename)
            .filter(String::isEmpty).count();
    if (count == pictures.length) {
        responseEntity.setCode(ResponseEntity.ERROR);
        throw new NullOrEmptyException("图片不能同时为空");
    }
    responseEntity.setCode(ResponseEntity.OK);
    responseEntity.setMessage("上传成功");
    return responseEntity;
}

Front‑end HTML

The name attribute of the file input must correspond to the controller parameter.

<div class="container">
    <div class="avatar-upload">
        <div class="avatar-edit">
            <input type='file' name="pictures" id="imageOne" accept=".png, .jpg, .jpeg"/>
            <label for="imageOne"></label>
        </div>
        <div class="avatar-preview">
            <div id="imageOnePreview" style="background-image: url(http://example.com/placeholder.jpg);"></div>
        </div>
    </div>
</div>

JavaScript preview

function readURLOne(input) {
    if (input.files && input.files[0]) {
        var reader = new FileReader();
        reader.onload = function (e) {
            $('#imageOnePreview').css('background-image', 'url(' + e.target.result + ')');
            $('#imageOnePreview').hide();
            $('#imageOnePreview').fadeIn(650);
        };
        reader.readAsDataURL(input.files[0]);
    }
}
$('#imageOne').change(function () {
    readURLOne(this);
});

JavaScript upload

function getUpload() {
    var formData = new FormData($('#picForm')[0]);
    $.ajax({
        url: '/pic',
        type: 'POST',
        dataType: "json",
        data: formData,
        processData: false,
        contentType: false,
        success: function (data) {
            window.confirm(data.message);
            window.location.reload();
        },
        error: function (res) {
            alert("失败");
        }
    });
}

Result screenshots

Initial page:

After uploading and previewing:

Upload size configuration

spring.servlet.multipart.enabled=true
spring.servlet.multipart.max-file-size=20MB
spring.servlet.multipart.max-request-size=20MB

File configuration

spring.servlet.multipart.enabled=true            # Enable multipart support
spring.servlet.multipart.file-size-threshold=0B # Threshold for writing to disk
spring.servlet.multipart.location=               # Directory for uploaded files
spring.servlet.multipart.max-file-size=1MB      # Max single file size
spring.servlet.multipart.max-request-size=10MB # Max request size
spring.servlet.multipart.resolve-lazily=false   # Lazy parsing flag

Exception handling

Spring Boot’s global exception handling can be used by annotating a class with @ControllerAdvice and defining methods with @ExceptionHandler.

@ControllerAdvice
@Slf4j
public class CommonExceptionHandler extends ResponseEntityExceptionHandler {

    @ExceptionHandler(NullOrEmptyException.class)
    @ResponseBody
    public ResponseEntity<String> nullOrEmptyExceptionHandler(HttpServletRequest request, NullOrEmptyException exception) {
        log.info("nullOrEmptyExceptionHandler");
        return handleErrorInfo(request, exception.getMessage());
    }

    @ExceptionHandler(value = Exception.class)
    @ResponseBody
    public ResponseEntity<String> defaultErrorHandler(HttpServletRequest request, Exception exception) {
        log.info("defaultErrorHandler");
        return handleErrorInfo(request, exception.getMessage());
    }

    private ResponseEntity<String> handleErrorInfo(HttpServletRequest request, String message) {
        ResponseEntity<String> responseEntity = new ResponseEntity<>();
        responseEntity.setMessage(message);
        responseEntity.setCode(ResponseEntity.ERROR);
        responseEntity.setData(message);
        responseEntity.setUrl(request.getRequestURL().toString());
        return responseEntity;
    }
}

Common pitfalls

If the controller returns a view name, do not add @ResponseBody on the class or method, otherwise the view name will be serialized as JSON.

Ensure the front‑end parameter name matches the back‑end method parameter; otherwise a 405 error may occur.

When using Lombok in IDEA, enable Annotation Processing in the IDE settings.

Complete source code is available at: https://github.com/modouxiansheng/Doraemon/tree/master/springdemo

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

JavaScriptException Handlingfile uploadSpring MVCMultipartFile
Programmer DD
Written by

Programmer DD

A tinkering programmer and author of "Spring Cloud Microservices in Action"

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.