文件上传

一. http协议规定:

  1. 必须使用POST方式提交请求;

  2. 在HTML页面表单中必须配置 enctype="multipart/form-data" (表示数据使用什么样的编码方式);

另外,在HTML页面表单中必须使用 <input type="file">控件

二. 基于SpringMVC的文件上传

简易客户端:

<form method="post" enctype="multipart/form-data" action="/upload">
    <h3>选择文件</h3>
    <input type="file" name="file" placeholder="请选择文件">
   <input type="submit" value="提交">
</form>

简易服务端:

@PostMapping("/upload")
public String upload(MultipartFile file) throws IOException {
    file.transferTo(new File("d:1.jpg"));
    return "OK";
}

  1. 文件大小:默认上传大小是有限制的,如果服务端报FileSizeLimitExceededExceprion,说明是文件大小受限,如果需要自定义,就向SpringBoot容器中添加一个MultipartConfigElement对象

    在配置类中添加以下代码:

@Bean
public MultipartConfigElement multipartConfigElement(){
    MultipartConfigFactory multipartConfigFactory = new MultipartConfigFactory();
    // 设置文件上传最大限制为 5 M
    multipartConfigFactory.setMaxFileSize(DataSize.ofMegabytes(5));
    // 设置请求最大限制为 6 M
    multipartConfigFactory.setMaxRequestSize(DataSize.ofMegabytes(6));
    return multipartConfigFactory.createMultipartConfig();
}

    注意:全局的上传限制和控制器中的文件上传限制应该同时存在

        全局的上传限制:自定义上传限制;拦截明显的错误(即明显超出大小限制)请求

        控制器上传限制:划分业务上传,根据业务不同自定义上传限制

  2. 关于文件可以使用api获取文件相关属性.如:

    3. 关于文件名称,在写入磁盘时,需要定义其文件名和扩展名,一些特殊文件只有文件名没有扩展名或者在Linux和MacOS中隐藏文件只有文件名而且是以点开头

    4. 上传是为了下载,所以,所有的文件上传的路径必须是可以通过hkttp访问到的位置,解决方法:

    1) 使用 HttpServletRequest 对象获取可访问的webapp路径(父级路径定位到request.gettServletContext().getRealPath("")),将其上传到webapp目录下.

      2) 使用SpringBoot或者SpringMVC自定义资源目录,http可以直接访问该资源目录

      在配置文件中添加以下配置

spring.resources.static-locations[0] = file:e:/upload, 
spring.resources.static-locations[1] = file:e:/img
spring.resources.static-locations[2] = classpath:/static

      注意:

        ① 静态目录可以配置多个

        ② 配置时如果没有配置原静态目录(static目录),则该目录下的资源文件就不可用了,需要显式的配置

      进行上传时,只需要写入到该目录下,既可以通过http访问

    5. 文件类型

    使用contentType进行文件类型判断,只需要获取文件的类型,然后与允许类型进行比较即可,可以将文件类型创建为一个列表,调用contains方法判断即可

    6. 关于其他限制,如空判断,大小判断只需要调用相应的api进行判断即可

    7. 关于使用ajax异步请求的方式发送请求

    $.ajax({
        url: '/upload',
        type: 'POST',
        data: new FormData($("#form")[0]),
        processData: false,
        contentType: false,
        success: function (json) {
            // 处理响应
        }
    });

    注意:

      1)  enctype="multipart/form-data" 的form表单数据必须是FormData类型,传入该表单

      2) 上传文件的ajax请求必须配置processData: false和contentType: false这两项

      3) contentType在此处填false的原因是告诉ajax函数data数据已经处理过,不需要进行再处理

三. 使用base64编码方式的上传(一般是图片)

  1. 客户端

     提交请求:

$("#send").click(function () {
        var files = $('#background_pic')[0].files
        var file = files[0];
        var reader = new FileReader();
        reader.readAsDataURL(file);
        reader.onload = function (theFile) {
            var image = new Image();
            // 图片可以得到base64编码
            image.src = theFile.target.result;
        var img = image.src.replaceAll("%", "-")
var data = { img: image.src } $.ajax({ url:'/upload', type: 'POST', data: data, dataType: 'json', success: function (json) { if(json.status != 200){ alert("上传图片失败!请稍后重试!"); }else { alert("上传成功!"); } } }) } });

    此外,使用种方式可以对图片在前端进行校验(校验内容自定义即可)

function checkImg(files){
        var file = files[0];
        var fileTypes = [".jpg", ".png",".gif",".jpeg"];
        var filePath = file.name;
        var flag = false;
        if(filePath){
            var fileEnd = filePath.substring(filePath.indexOf("."));
            for (var i = 0; i < fileTypes.length; i++) {
                if (fileTypes[i] == fileEnd) {
                    flag = true;
                    break;
                }
            }
        }
        if (!flag){
            alert("请上传 jpg、png、jpeg 的图片格式文件!");
            $('#background_pic').val(null);
            return;
        }
        var reader = new FileReader();
        reader.readAsDataURL(file);
        var ret = [];
        reader.onload = function (theFile) {
            var image = new Image();
            image.src = theFile.target.result;
            //console.log(image.src);
            image.onload = function () {
                width = this.width;
                height = this.height;
                console.log(width!=1920 + " and " + height!=1080)
                if (width != 1920 || height != 1080) {
                    alert("为了更好的显示效果,请使用分辨率为1920×1080的图片!");
                    $('#background_pic').val(null);
                    return;
                }
            };
        }
    }
View Code

  2. 服务端

   @PostMapping("/upload")
    public String upload(String img){
        // 格式: data:image/jpeg;base64,{{具体内容的数据编码}}或者data:text/txt;base64,{{具体内容的数据编码}}等等
        // 传输过程中会将 + 替换为空格
        // 前端自定义将 % 替换为 -
        img = img.replaceAll(" ", "+");
        img = img.replaceAll("-", "%");
        String[] strArr = img.split(",");
        String dataType = strArr[0];
        String imgBase64 = strArr[1];
        String suffix = dataType.substring(dataType.indexOf("/"), dataType.indexOf(";"));
        String parent = "e:/img";
        String child = UUID.randomUUID().toString() + "." + suffix;
        File file = new File(parent, child);
        BASE64Decoder decoder = new BASE64Decoder();

        try {
            byte[] b = new byte[0];
            b = decoder.decodeBuffer(imgBase64);
            for (int j = 0; j < b.length; ++j) {
                //调整异常数据
                if (b[j] < 0) {
                    b[j] += 256;
                }
            }
            OutputStream out = new FileOutputStream(file);
            out.write(b);
            out.flush();
            out.close();
        } catch (IOException e) {
            throw new RuntimeException("描述");
        }
        return "OK";
    }

 

原文地址:https://www.cnblogs.com/xiao-lin-unit/p/14583899.html