超详细的实现上传文件功能教程,文件上传实现。

Django中实现文件上传功能 在web开发中,文件上传与下载是常见的功能,在Django中实现文件的上传与下载也非常简单,实现步骤与其他功能实现类似,1. 新建一个模板,2. 编写模板对应的view函数,3. 配置view与模板关联的url。具体实现如下: 1. 新建一个模板:      新建一个用于上传文件的模板(本文的模板是基于bootstrap的),内容如下:       阅读详情
AI摘要

本文深入讲解文件上传的各种方式,包括base64上传、form表单上传及Java模拟表单上传,探讨不同场景下的最佳实践。

重要声明:本文章仅仅代表了作者个人对此观点的理解和表述。读者请查阅时持自己的意见进行讨论。

本文更新不及时,请到原文地址浏览:《超详细的实现上传文件功能教程,文件上传实现。》。

一、文件上传的方式

在程序的世界里,没有什么功能的实现方式是单一的。上传文件也不例外,我们有很多种能够实现文件上传的方法。但我们最终要采用的,必然是最熟悉、最常用的方法。文件上传通常有下面的方法进行:

  1. 将内容进行base64,将base64字符串结果通过普通请求提交给后台。
  2. 直接使用浏览器的form表单进行文件上传。
  3. 使用java模拟表单(自己封装表单格式数据)进行文件上传。

这些文件上传方式,都是基于HTTP协议的基础,它并没有强制限定了我们要如何去编码或处理数据,相反协议的存在使世界上所有的程序差异化不是那么太大。HTTP协议规定了,提交大量数据时,可以使用POST请求来进行提交。是的,大多数后台程序都只会在POST请求下去获取大量上传的数据,而不会在GET请求下去获取。你要知道,如果你不规范提交,当然也是可以不规范的从GET下获取到提交的数据。但极其不建议这样做。

如果你对HTTP协议还不是很了解,你可以通过这篇文章来入门对HTTP协议的了解:《【HTTP,Java】认识HTTP协议,在互联网世界里翱翔》。

二、base64 上传文件

1、HTML网页内使用base64

如果你要在网页中使用base64的方式将文件提交给后台,那么你不得不面临一个很严峻的问题就是:如何在网页中奖文件内容读取并转换成base64的数据。很幸运HTML5为我们提供了解决方案。

FileReader提供了读取文件的能力。但它可不是你想象的提供一个文件路径就可以读取了。它能读取的文件需是来自下面的途径:

  1. 通过<input type="file">节点选择的文件。
  2. 通过拖放(DataTransfer)文件事件得到的文件。
  3. Canvas通过mozGetAsFile()方法返回的文件。

下面以input选择的文件为例进行讲解。

a、选择文件并转换为base64

直接在html文件中写一个input并将其type设定为file即可立即实现一个文件选择功能。现在同时给出读取文件的示列代码:

<body>
    <!-- 文件选择和上传按钮 -->
    <input type="file" id="fileSelecter"><button onclick="uploadFile()">上传</button>

    <!-- 上传逻辑 -->
    <script>
        function uploadFile() {

            // 找到文件文件选择框
            var fileInput = document.querySelector("#fileSelecter");

            // 获取选择的文件
            // (因为input是支持选择多个文件的,所以获取文件通过files字段,如果单个文件也是在这个files列表里。)
            var file = fileInput.files.item(0);

            // 判断一下
            if (file == null) {
                // 没有选择文件。就什么都不处理。
                return;
            }

            // 使用FileReader读取文件。
            var fileReader = new FileReader();

            fileReader.addEventListener("error", function (ev) {
                // 文件读取出错时,执行此方法。
                // 通过 fileReader.error 可以获取到错误信息。
            });

            fileReader.addEventListener("load", function (ev) {
                // 文件读取成功后调用此方法。
                // 通过 fileReader.result 即可获取到文件内容。
            });

            fileReader.addEventListener("loadstart", function (ev) {
                // 读取开始时此方法被调用。
            });

            fileReader.addEventListener("loadend", function (ev) {
                // 文件读取结束时执行此方法。
                // 无论读取成功,还是读取失败。
                // 总之,在结束读文件操作时,此方法都会调用。
            });

            fileReader.addEventListener("abort", function (ev) {
                // 文件读取被中断时,此方法调用。
                // 你可以通过 fileReader.abort() 方法随时中断文件的读取。
            });

            fileReader.addEventListener("progress", function (ev) {
                // 读取文件过程不是一次性读完的,会进行多次读取。
                // 没读取一次,本方法执行一次。
            });

            // 将文件内容读取为 base64 内容。通过 fileReader.result 即可返回base64的数据内容。
            fileReader.readAsDataURL(file);
        }
    </script>
</body>

上述代码中详细注释了使用FileReader如何读取文件的使用方式。通过监听load事件,即可获取到文件读取的结果数据。如果你将这个结果打印出来,你将看到类似下面的数据:

data:image/jpeg;base64,/9j/4AAQSkZJergxawffwetcwgIKFUEGNiwgefnwkef...KCAcHCg0

如果你看到了类似的数据。那么你就算是成功一半了。

注意: 其中data:image/jpeg;base64,这一段属于对base64数据体的描述。文件真实base64内容只有逗号后面部分。如果后端接口明确告知你只需要传递后面的数据,那么你还需要自行将前面的描述去除。

b、上传结果到接口

现在建立请求将得到的结果提交到服务器即可。在load监听事件里我们可以成功的获取到base64的结果,因此只需要将提交数据代码写在监听里即可。这里我直接使用JQuery的post方法进行数据提交。代码如下:

fileReader.addEventListener("load", function (ev) {
    // 文件读取成功后调用此方法。
    // 通过 fileReader.result 即可获取到文件内容。
    var result = fileReader.result;
    $.post("https://www.microanswer.cn/test/uploadBase64", {
        base64Data: result
    }, function (response) {
        // 服务器响应了我们的上传请求。
    });
});

如果你对JQuery的post方法不是很熟悉,请参考:【JQuery】JQuery常用方法总结、大全。

2、Java程序内使用base64

在使用java作为后台程序的时候,有时候也经常通过http向其他服务器上传内容,那如果是使用base64方式,如何将数据以base64提交呢?其实非常简单,和上一小节里提到的BASE64Decoder有点类似,Java里还有一个类BASE64Encoder,他可以方便的将文件转为一个base64字符串,看下面的示列代码:

// 将文件转为base64字符串
public String file2Base64(String filePath) {
    // 建立文件对象
    File file = new File(filePath);
    BASE64Encoder base64Encoder = new BASE64Encoder();
    ByteArrayOutputStream out = null;
    FileInputStream fileInputStream = null;
    // 标准流读取代码模板。
    try {
        out = new ByteArrayOutputStream();
        fileInputStream = new FileInputStream(file);
        byte[] data = new byte[1024];
        int datasize = 0;
        while ((datasize = fileInputStream.read(data)) != -1) {
            out.write(data, 0, datasize);
        }
        out.flush();
    } finally {
        try {
            if (fileInputStream != null) {
                fileInputStream.close();
            }
        }catch (Exception ignore) {}
    }
    return base64Encoder.encode(out.toByteArray());
}

有了base64字符串,就可以方便的进行上传了。相信后台程序一般都会有一个封装好了的网络请求工具类,下面示列一个典型的上传代码:

String base64 = file2Base64("D:/temp/test.doc");
HashMap<String, String> param = new HashMap<>();
param.put("base64Data", base64);
String response = HttpUtil.postFormUrlEncode("https://www.microanswer.cn/test/uploadBase64", param);

此处使用的HttpUtil工具你可以通过下面的maven依赖获取:

<dependency>
    <groupId>cn.microanswer</groupId>
    <artifactId>HttpUtil</artifactId>
    <version>1.0.1</version>
</dependency>
3、后台接口

上述请求中,将数据以 base64Data 字段提交给了接口。现在只需要处理服务器响应后的事情了。先看看接口是如何获取数据的把:

@RequestMapping("/uploadBase64")
public Object uploadBase64Data(HttpServletRequest request) throws Exception {
    String base64Data = request.getParameter("base64Data");

    // 保存文件后缀名。
    String fileExtName = "";
    // 保存文件真实的base64数据
    String realBase64;

    // 判断是否有前缀
    if (base64Data.startsWith("data:") && base64Data.contains("base64,")) {
        String[] typeAndData = base64Data.split(",");

        // 截取 data:image/jpeg;base64, 为=>  jpeg;base64,
        String tempType = typeAndData[0].split("/")[1];
        // 拿到 ; 号前面的内容作为文件后缀。
        fileExtName = "." + tempType.substring(0, tempType.indexOf(";"));

        // 拿到真实base64数据。
        realBase64 = typeAndData[1];
    } else {
        // 没有前缀,则认为所有字符串都是base64实际内容。
        realBase64 = base64Data;
    }

    // 对 base64 字符串进行原数据读取
    byte[] bytes = new BASE64Decoder().decodeBuffer(realBase64);

    // 构建文件将数据保存
    File file = new File("D:/temp/" + UUID.randomUUID().toString() + fileExtName);
    FileOutputStream fo = new FileOutputStream(file);

    // 输出文件内容
    fo.write(bytes);
    fo.flush();
    fo.close();

    // 返回成功
    JSONObject object = new JSONObject();
    object.put("code", 200);
    object.put("msg", "上传成功");
    return object;
}

三、form表单上传文件

对于前端来说,这种方式无疑是最简单的上传方式,因为甚至可以做到不写一点JavaScript代码就实现了。为了对前端上传文件有更深入了解,使用form表单上传时也有两种上传方案,一种是直接使用form节点的,另一种则是通过FromData对象来完成。

1、使用html的form节点

下面直接展示示列代码:

<form method="post"
      action="https://www.microanswer.cn/test/uploadFile"
      enctype="multipart/form-data">
    请选择文件:<input type="file" name="fileData"><br>
    请输入文件描述:<input type="text" name="fileDescription"><br>
    <input type="submit" value="提交">
</form>

这样,前端就实现了文件上传了。提交给接口uploadFile要怎么去获取里面的文件,前端不用管了。

2、使用 FormData 对象

当使用FormData完成文件上传时,事情就变得稍微复杂一点了。但是有它的优势。直接在页面上使用form表单会造成页面的跳转,上传成功后就不会再停留在当前页面了。而使用 FormData 进行文件上传则可以完成异步上传,达到不跳页面的效果。

首先要清除一点,FormData对象要提交数据时,其文件数据是来自于<input type="file">选择的文件。加入现在你已经选好了文件并且拿到了file对象,那么下面示列一个如何将此数据上传到服务端的代码:

// 文件上传方法。 callback 是上传完成回调。
function uploadFile(file, callback) {
    var formData = new FormData();
    formData.append("fileData", file); // 添加文件到 formData。
    formData.append("fileDescription", "文件上传描述信息。"); // 添加一个描述字段。

    // 进行上传
    $.ajax({
        url: "https://www.microanswer.cn/test/uploadFile",
        type: 'post',
        data: formData,
        contentType: false, // 不指定contentType,这样让JQuery主动识别
        processData: false, // 不让JQuery处理上传的数据,
        dataType: 'json',   // 预期返回数据格式。
        success: function (response) {
            callback(response);
        },
        error: function (xmlHttpRequest, statusStr, exception) {
            callback(undefined, exception);
        }
    });
}

代码中可以看到,首先使用 FormData 创建了一个实例,然后将文件和描述信息放入其中,最后通过 JQuery 的 ajax 方法将数据提交给后台接口。

四、使用Java模拟表单

java里没有类似formdata的上传文件辅助类,我们需要根据表单在上传文件时数据具体是如何进行提交的流程进行自己使用java来实现。摆在我们面前的首要任务就是要搞明白表单提交的数据结构,只有详细了解了其结构,才能使用Java进行完美的模拟。

1、文件上传的数据内容格式

通过表单上传文件显然是HTTP协议内的一部分内容,因此我们不妨直接翻开HTTP协议里针对表单上传文件相关的定义文档:RFC1867。下面是一些重点内容的截取部分(博主能力有限,翻译得不好还请将就凑合):

multipart/form-data的定义

数据格式内容举例

ww

2、Java代码实现表单

通过上述HTTP协议定义文档中的描述,相信文件表单在数据提交过程中数据传输方式和格式已经有了大致的了解。现在是时候使用Java实现这样一个功能了。

a、单个表单文件单元

根据定义,一个input可以支持选择多个文件的,而在传输时,每个文件的传输需要提供一些基本信息。因此,直接为单个文件单元实现为一个类:

/**
 * InputFile.java
 * 用于放在表单 Input 里的文件单元。
 */
public class InputFile {

    // 保存当前需要传递的文件引用。
    private File file;

    // 如果要传递的数据直接是二进制数据了,这里也提供一个变量,使支持二进制数据直接传递。
    private byte[] byteData;

    // 在不清楚上传的数据是什么,但确切知道上传的内容是一个inputstream里的内容。这里也提供一个变量,使支持输入流直接传递。
    private InputStream inputStream;

    public InputFile(File file) { this.file = file; }

    // 对于数组,不要直接引用,而是取一份其拷贝的数据。
    public InputFile(byte[] byteData) {
        this.byteData = new byte[byteData.length];
        System.arraycopy(byteData, 0, this.byteData, 0, byteData.length);
    }
    public InputFile(InputStream inputStream) { this.inputStream = inputStream; }


    // 当进行提交时,使用此方法,此方法将会把当前单元持有的[文件\数据\流]进行上传。
    public void submit(OutputStream outputStream) throws Exception{

        // 输出是,首先建立基本信息输出。
        StringBuilder baseInfo = new StringBuilder();

        if (file != null) {
            // 有文件,则输出文件。
            baseInfo.append(" filename=\"").append(file.getName()).append("\"").append(Constant.LINE_SEPARATOR);
            baseInfo.append("Content-Type: ").append(new MimetypesFileTypeMap().getContentType(file)).append(Constant.LINE_SEPARATOR);
            baseInfo.append(Constant.LINE_SEPARATOR);

            inputStream = new FileInputStream(file);

        } else {
            // 输出数据 或 流,但因为不知道名称,因此填写一个随机名称。
            baseInfo.append(" filename=\"")
                    .append(UUID.randomUUID().toString().replaceAll("-", ""))
                    .append("\"")
                    .append(Constant.LINE_SEPARATOR)
                    .append("Content-Type: application/octet-stream").append(Constant.LINE_SEPARATOR)
                    .append(Constant.LINE_SEPARATOR);
        }

        outputStream.write(baseInfo.toString().getBytes(Constant.charset));

        // 将具备的流信息输出。
        if (inputStream != null) {
            byte[] datas = new byte[1024];
            int datasize = 0;

            while ((datasize = inputStream.read(datas))!= -1) {
                outputStream.write(datas, 0, datasize);
            }

            if (file != null) {
                inputStream.close();
            }
        } else if (byteData != null && byteData.length > 0) {
            // 将数据输出。
            outputStream.write(byteData);
        }

        outputStream.write(Constant.LINE_SEPARATOR.getBytes(Constant.charset));
    }
}
b、Input单元

input单元里可以放置一个键值对,用来传递数据,同时,它还可以传递键和一系列文件,上一节的文件单元就可以放在这个Input单元中。则可以设计出 Input单元类如下:

/**
 * Input.java
 * 表单里面的一条input输入单元。
 */
public class Input {
    // 表单支持的类型枚举
    public enum Type { text,file }

    // 此 input 要提交的name值。
    private String name;

    // 此 input 要提交的value值。当type为text时才会提交此数据。
    private String value;

    // 此 input 要提交的文件。当type为file时才会提交此数据。
    private ArrayList<InputFile> inputFiles;

    // 此表单的类型,目前只有:text 和 file
    private Type type;

    // 允许直接使用键值对构造一个text的input。
    public Input(String name, String value) {
        this.name = name;
        this.value = value;
        this.type = Type.text;
    }

    // 允许使用name和文件列表构造一个file的input。
    public Input(String name, InputFile... inputFile) {
        this.name = name;
        this.inputFiles = new ArrayList<>();
        this.inputFiles.addAll(Arrays.asList(inputFile));
        this.type = Type.file;
    }

    // 在提交前,允许添加文件。
    public Input addFile(InputFile inputFile) {
        this.inputFiles.add(inputFile);
        return this;
    }

    // 在提交前,允许修改要提交的值。
    public Input setValue(String value) {
        this.value = value;
        return this;
    }


    // 将此input内的数据进行提交。
    public void submit(OutputStream outputStream) throws Exception {
        // 先构建基本信息输出。
        StringBuilder baseInfo = new StringBuilder();
        baseInfo.append("content-disposition: form-data; name=\"").append(name).append("\";");

        if (type == Type.text) {
            baseInfo.append(Constant.LINE_SEPARATOR);
            baseInfo.append(Constant.LINE_SEPARATOR);
            baseInfo.append(value);
            baseInfo.append(Constant.LINE_SEPARATOR);

            String s = baseInfo.toString();
            outputStream.write(s.getBytes(Constant.charset));
        } else {

            if (inputFiles != null && inputFiles.size() > 0) {

                if (inputFiles.size()  == 1) {

                    outputStream.write(baseInfo.toString().getBytes(Constant.charset));
                    inputFiles.get(0).submit(outputStream);
                } else {
                    String boundary = UUID.randomUUID().toString().replaceAll("-", "").substring(0, 6);

                    // 此input有多个文件。先输出内容体的基本信息。
                    baseInfo.append(Constant.LINE_SEPARATOR);
                    baseInfo.append("Content-Type: multipart/mixed, boundary=").append(boundary);
                    baseInfo.append(Constant.LINE_SEPARATOR);
                    baseInfo.append(Constant.LINE_SEPARATOR);

                    // 循环输出文件内容
                    for (InputFile infile: inputFiles) {
                        baseInfo.append("--").append(boundary).append(Constant.LINE_SEPARATOR);
                        baseInfo.append("content-disposition: attachment;");
                        outputStream.write(baseInfo.toString().getBytes(Constant.charset));
                        infile.submit(outputStream);

                        baseInfo = new StringBuilder();
                    }

                    // 追加上最后一个 boundary。
                    baseInfo.append("--").append(boundary).append("--").append(Constant.LINE_SEPARATOR);
                    outputStream.write(baseInfo.toString().getBytes(Constant.charset));
                }
            }
        }
    }
}

c、 form 表单

实现了 Input 之后,最后一个便是form实现了,form只需要实现其基本的数据组装即可完成:

/**
 * Form.java
 * 模拟HTML页面表单行为。
 */
public class Form {

    private ArrayList<Input> inputs;

    public Form() {
        this.inputs = new ArrayList<>();
    }

    // 往表单中添加一个input数据。
    public Form addInput(Input input) {
        this.inputs.add(input);
        return this;
    }

    // 提交这个表单。传入你要提交到的目标地址。
    // 此处代码比较简单,可以按需自己实现或修复其中存在的问题。
    public String submit(String url) throws Exception {
        if (inputs == null || inputs.size() == 0) {
            throw new NullPointerException("请至少添加一个要提交的表单数据。");
        }

        URL url1 = new URL(url);
        URLConnection urlConnection = url1.openConnection();

        HttpURLConnection c = (HttpURLConnection) urlConnection;

        // 设置请求方式、
        c.setRequestMethod("POST");
        c.setDoOutput(true);
        c.setDoInput(true);

        String boundary = UUID.randomUUID().toString().replaceAll("-", "").substring(0, 6);

        // 设置header
        c.setRequestProperty("Content-Type", "multipart/form-data, boundary=" + boundary);

        // 进行传输。
        OutputStream outputStream = c.getOutputStream();
        for (Input in : inputs) {

            outputStream.write(("--" + boundary + Constant.LINE_SEPARATOR).getBytes(Constant.charset));
            in.submit(outputStream);
        }

        outputStream.write(("--" + boundary + "--").getBytes(Constant.charset));
        outputStream.flush();

        // 获取结果
        InputStream inputStream = c.getInputStream();

        // 读取结果字符串。
        InputStreamReader reader = new InputStreamReader(inputStream, Constant.charset);
        char[] chars = new char[256];
        int charsize=  0;

        StringBuilder result = new StringBuilder();
        while ((charsize = reader.read(chars))!= -1) {
            result.append(chars, 0, charsize);
        }
        c.disconnect();

        return result.toString();
    }
}
d、测试结果

现在InputFile、Input、Form 类都已完成开发,不妨进行一下测试:

// 构建一个表单
Form form = new Form();

// 加入一个普通的键值对。
form.addInput(new Input("name", "Jack"));

// 加入一个包含多个文件的input。
form.addInput(new Input("fileData",
        new InputFile(new File("C:\\Users\\Micro\\Desktop\\file1.jpg")),
        new InputFile(new File("C:\\Users\\Micro\\Desktop\\file2.jpg"))
));

// 提交到指定地址。
String result = form.submit("https://www.microanswer.cn/test/uploadFile");

// 打印结果
System.out.println("提交结果:" + result);

// 输出:提交结果:{"msg":"success","code":200,"data":null}

完美通过。

e、附加类

在上述几个类中,使用了一个常量类,其代码如下:

public class Constant {

    /**
     * 表单中上传文件,使用的换行必须是 \r\n。
     */
    public static final String LINE_SEPARATOR = "\r\n";

    /**
     * 表单中字符串的编码。
     */
    public static final Charset charset = StandardCharsets.UTF_8;

}

五、后台接收表单文件

本文主要讲了Java后台如何实现获取表单内的数据,下面将分别对spring后台和原生的servlet后台进行示例。

1、Spring后台

如果你的后台使用了Spring框架,那么你就幸运了,你可以十分方便的拿到表单上传上来的文件。只需要通过一些简单的注解就可以完成,下面示列了一个典型的Controller接口方法,用于获取表单上传上来的文件:

@RequestMapping("/uploadFile")
public Object uploadFileTest(
        @RequestParam(value = "fileData") MultipartFile multipartFile,
        HttpServletRequest request
) throws Exception {
    // 即可拿到已上传的文件内容。如果你不处理,这个文件就会在本次请求结束时被删除
    InputStream in = multipartFile.getInputStream();

    return Util.buildReturnJson(WebApplication.Code.SUCCESS, "success", null);
}

这个方法针对input里只有一个文件时非常方便。如果某个input里包含了多个文件,这个方法似乎没法获取到更多的文件。(如果这个方法能的法话,还请大佬评论指正。)

当你希望获取到某个input下的所有上传的文件时。你可以用下面的方法:

@RequestMapping("/uploadFile")
public Object uploadFileTest(HttpServletRequest request) throws Exception {

    // 使用 spring 提供的内置工具
    StandardMultipartHttpServletRequest r = new StandardMultipartHttpServletRequest(request);

    // 可以直接获取到input里如果是text类型的值。
    String name = r.getParameter("name");

    // 可以通过这样的方式获取到某个input下的所有文件。
    // 这里就获取了input的name为files时,提交上来的所有文件。
    List<MultipartFile> files = r.getMultiFileMap().get("files");

    return Util.buildReturnJson(WebApplication.Code.SUCCESS, "success", null);
}
2、servlet 实现

在servlet中获取表单上传的文件相对比spring里复杂,但其实spring只是把servlet的封装了一下。咱们java后台的表单解析功能是自带就有的。下面给出一个示例:

public void doPost(HttpServletRequest request, HttpServletResponse response) throws Exception {
    // 获取表单的所有 part 内容。
    // 一个 text 的input 是一个 part
    // 一个 file 的input 里可能有多个part(因为可以多选文件嘛),这些part的name都是 input的name。
    Collection<Part> parts = request.getParts();
    Iterator<Part> iterator = parts.iterator();
    while (iterator.hasNext()) {
        // 获取到表单里的每个part。
        Part part = iterator.next();
        part.getName(); // 对应了 input 的 name 属性。
        part.getSubmittedFileName(); // 对应了 input=file 时 提交的文件的真实名字。(当input不是file类型时此方法返回的null)
        part.getInputStream();  // 对应了 input=file 是文件时的文件输入流。input=text时,其value值也通过此流读取。
        // todo 实现自己的业务。
    }
}

六、总结

无论使用什么方式进行文件上传,只要对HTTP协议有一定的了解,都可以轻松完成各种需求的开发。为什么要针对表单进行模拟来上传文件,因为这是大多数服务器的上传文件方式,许多服务端也都默认支持解析表单文件,因此客户端的上传也许迎合服务器所支持的使用表单进行文件上传。

如果你还对HTTP协议不是很了解,可通过这篇文章进行入门:《【HTTP,Java】认识HTTP协议,在互联网世界里翱翔》。

Spring Boot 实现文件上传下载功能 进入前端页面的 URL 为 http://localhost:8080/upload.html。该部分代码为 [2.2 文件上传功能实现](###2.2 文件上传功能实现) 的前端实现。文件下载则只是简单的 GET 请求。现有的 Web 框架都内置了处理文件上传的功能。指定了文件在请求体中的键,后端服务器将通过这个名称来获取文件数据。是用来表示上传的文件,服务器会自动解析该文件并进行处理。,并选择一个文件进行上传。将文件上传的具体逻辑抽象到一个。将文件上传的具体逻辑抽象到一个。请求,下载指定的文件。 阅读详情

相关推荐

SpringBoot学习(汇总版)

一、SpringBoot简介 1.1、Spring能做什么 1.1.1、Spring的能力及生态 1.1.2、Spring5的响应式编程 1.2、SpringBoot是什么 百度百科:Spring Boot是由Pivotal团队提供的全新框架,其设计目的是用来简化新Spring应用的初始搭建以及开发过程。该框架使用了特定的方式来进行配置,从而使开发人员不再需要定义样板化的配置。通过这种方式,Spring Boot致力于在蓬勃发展的快速应用开发领域(rapid application developmen

weixin_45495161的博客 4339

超详细的两种文件上传方式

本地存储即使将想要上传的文件上传到本地文件加上,当你启动项目时,自己的window机就相当于一个服务器,本地磁盘就可以成为文件上传的储存地。由于为了解决本地存储的缺点,就是用了阿里云OSS存储器,将图片存储到一个自己公共的云端上,便于自己操纵自己的文件。

weixin_52197063的博客 7891

Spring Boot文件上传功能的实现!超详细!

文件上传功能在很多系统中都占据非常重要的份置,软件开发人员在实现文件上传时,除了需要确保程序代码的稳健性和高维护性外,还需要从社会责任的角度审的需求,秉承合法、合规的职业理念进行数据读写,避免程序在保存用户上传的文件时造成不良的社会影响。例如,应该关注保护用户的隐私,避免用户的隐私泄露,以及杜绝上传非法文件。

元气满满的霄霄滴博客 4269

文件上传的原理

文件上传

m0_64372028的博客 7141

Bootstrap框架下的文件上传插件实现教程

在如今的Web应用中,文件上传是基本功能之一。Bootstrap文件上传组件提供了一个简单的界面,用户可以通过它上传文件,同时与开发者交互。这种组件不仅美观而且功能强大,通常包含多种实用的特性,比如上传进度、文件预览和拖放上传等。在这一章节中,我们将对Bootstrap文件上传组件做一个整体的介绍,包括其基本工作原理以及如何在Web应用中集成和利用它。接下来章节将会对这一组件做更深入的分析和实践应用。在引入了File Input插件之后,我们需要将其初始化,以便利用它的高级功能。

weixin_29717341的博客 1159

野火STM32F407(骄阳)+无刷直流驱动板+永磁同步电机控制学习记录(四)(基于HAL库)

以上内容都是参考别人资料自学的,很多地方都是凭感觉,因为理论部分不太会算,只要电机能转就行,其他性能指标都没考虑,因为不会,所以这纯属是学习记录帖。带宽在500时,电流波动小,但是响应很慢,就是堵转后不太容易恢复转动。速度环带宽设定小了,响应不够快,带宽设定大了波动比较大,电机感觉起来也震一点,而且,当带宽设到200的时候,启动直接就锁死了,应该是PI增益设定太大了。电流环带宽的试验:去掉速度环,让Iq_Set=2,Ud=0,此时电机是电流环闭环控制,用手堵转电机然后松开,看电流的波动以及响应情况。

XUEXIDEXIAOhai的博客 4553

java——文件上传

文件上传的简介:文件上传是指将本地计算机中的文件传输到网络上的服务器或另一台计算机上的过程。在 Web 开发中,文件上传通常指的是将用户通过 Web 页面提交的文件(如图像、文档、音频、视频等)传输到服务器端的操作。总结:服务端要想接收到从前端页面上传的文件,需要使用到一个api:MultipartFile,通过该api来接收上传的文件。而上传上来的文件是一个。基础实现:在上面的文件上传——入门的基础上,修改一下controller就行。最快的解决办法就是,修改本地存储的路径,输入一个存在的目录的路径。

学习笔记 1万+

手把手教你用FreeModbus RTU协议栈实现STM32与PLC通信(附Keil工程)

本文详细介绍了如何使用FreeModbus RTU协议栈在STM32上实现与PLC的工业通信。从环境搭建、工程配置到关键移植接口实现,提供了Keil工程模板和调试技巧,帮助开发者快速掌握Modbus RTU通信技术,适用于工业自动化领域的设备间通信需求。

weixin_42549037的博客 419

【JavaWeb】文件的上传

文件上传:将本地的文件通过流写入到服务器的过程。

wang_qiu_hao的博客 6830

ULN2003驱动28BYJ-48步进电机详解(附:51 32代码讲解)

本文介绍了28BYJ-48步进电机的驱动原理以及注意事项,并展示了极简 32 51驱动代码

qq_41818650的博客 1万+

使用fairseq从头开始训练一个中英神经机器翻译模型

前言 由于毕设是做神经机器翻译相关,所以先尝试一下神经机器翻译的整个流程是非常有必要的。故将在news-commentary-v15语料上训练有监督中英NMT模型的整个流程,包括工具和数据的准备、数据的预处理、训练及解码等过程,以及过程中遇到的问题和解决方案记录在此,以供后期回顾,也希望能够给予别人一些帮助。附本人博客 1 相关工具及目录结构 1.1 相关工具 除jieba是使用pip install安装外,其他几个工具都是建议直接克隆库到自己的用户目录中,方便使用其脚本(moses/subword-nmt

qq_42734797的博客 2万+

jsp实现文件上传下载功能

文件上传首先得引入两个jar包,建议在mvn库中下载,下载完粘贴到lib目录下 首先写上传文件的jsp界面 &lt;form action="UpLoadServet" method="post" enctype="multipart/form-data"&gt; &lt;font color="white" size="5px"&gt;文件上传功能(将你的照片,音乐

仲夏的博客 3万+

pyecharts可视化图表-tree:从入门到精通

本文系统介绍了树图(Tree Chart)的可视化技巧,包含基础实现、方向定制和环形布局等实例。树图能清晰展示层次结构数据,适用于组织架构、文件系统等场景。教程详细解析了pyecharts树图的核心配置项,包括数据准备、方向设置(下上、右左)和样式定制,并提供了完整代码示例。通过本指南,读者可快速掌握专业树图的构建方法,实现复杂层次数据的可视化呈现。

大数据内容个人总结与分享 1970

SpringBoot实现文件上传功能

大家使用spring-mvc来实现文件上传已经很简单了,其实spring这个团队非常的伟大,为什么这么说呢,使用spring-boot来实现文件上传功能更加的方便快捷, 废话不多上直接上代码 首先需要创建spring-boot项目这点都不用说,不会创建的建议搭建可以先学一下怎么来创建springboot项目。 由于只是实现一个简单的上传功能,所以在这里我就不在使用模板引擎了,直接在stati...

druidcaesa的博客 1万+

autoDL算力云装Xinference[坑与步骤]

在页面直接点击下载会出现下着下载进度条消失,试了几次才出现这个报错,现在我们就继续安装缺少的包吧。这一步成功绕开了系统盘空间限制。先租用一个合适的服务器,建议不要选最新版本,跟我选的一样即可,不然后面会出现。最近在 AutoDL 上尝试部署。🚫 不要直接使用以下命令。点击下面链接即可打开。

ngadminq的博客 2383

Taro React组件使用(5) —— RuiPasswordInput 密码输入框显示隐藏和清空

初始化时,需要将传入的 value 赋值给当前组件的 value, 不能直接修改 props 的 value;在组件内输出组件内的变量时,最好先判断输出函数是否定义,再输出,否则很容易引起报错。

止于至善 891

如何实现文件上传功能

开发工具与关键技术: VS MVC基础 作者:卢雅婷 撰写时间:2019/06/17 其实文件上传是我们平常与互联网交流的方式,发一篇文件要上传,同时我们从网上获取的文章、文件等等资源都是别人上传至网上的,所以说上传这个功能很常用哪它又是如何实现的呢?这就是我今天的分享内容上传文件功能的实现。(下面的代码来源于老师) 上传文件我们都知道点击上传按钮,再选择要上传的文件之类资料,确定即可上传,哪在这...

weixin_44538353的博客 1万+

uniapp微信小程序 - 解决苹果ios底部输入框被软键盘遮挡的问题,input/textarea底部输入框被弹出的软键盘挡住部分或全部遮住(解决uniApp小程序底部输入框,键盘弹起时页面整体上移

uniapp: IOS微信小程序输入框部分被软键盘遮挡问题,iOS微信小程序键盘弹出时输入框被挡住,uniapp小程序苹果IOS系统软键盘唤起导致底部输入框被遮挡的问题,ios 键盘弹出input输入框被遮挡,uniapp textarea输入框软键盘遮挡问题,苹果手机ios系统,解决uni-app微信小程序底部输入框,键盘弹起时页面整体上移 问题,关于手机端IOS系统微信中虚拟键盘遮挡input输入框问题的解决方案,uniapp使用输入框固定在底部键盘弹起把输入框挡住问题,安卓上没问题就苹果不行,仅ios

🏆 前端领域优质创作者 5596

SpringMVC文件上传功能实现

SpringMVC文件上传功能实现,SpringBoot文件上传,MultipartFile使用,以及MultipartHttpServletRequest获取上传文件内容。SpringBoot配置上传文件大小。

qq_43600166的博客 4725

Outlook Express 6 (OE6) for Win7/Win8/Win10

英文版 Outlook Express6.0, 兼容Win7/Win10/WinXP,解压就可用。

Data-Structures-and-Algorithm-Analysis-in-Java.pdf

作者: Weiss, Mark A. 出版社: Addison Wesley Data Structures and Algorithm Analysis in Java is an “advanced algorithms” book that fits between traditional CS2 and Algorithms Analysis courses. In the old ACM Curriculum Guidelines, this course was known as CS7. This text is for readers who want to learn good programming and algorithm analysis skills simultaneously so that they can develop such programs with the maximum amo...

MultipartFile实现文件上传功能

使用MultiPartFile实现文件上传功能,介绍了postman如何进行文件上传测试,以及如何实现文件下载功能。

weixin_45866737的博客 1万+

jre9下载 jdk9

(Java SE Runtime Environment 9.0) 9.0u175 官方最新版 【x86|x64】

Express与Multer集成:轻松实现文件上传功能教程

Multer是一个Node.js中间件,用于处理multipart/form-data类型的表单数据,这在文件上传场景中非常常见。它基于busboy库构建,可以轻松地与express框架集成。

1988

WINCC7.3破解文件

WINCC7.3硬件够破解文件,有需要的下载!WINCC7.3硬件够破解文件,有需要的下载!

selenium如何实现文件上传功能

在做web自动化时会碰到文件上传的实现功能,这个时候我们应当如何使用selenium进行文件的上传呢? 一,selenium直接上传 大家都知道我们在做selenium自动化时,必须要面临的就是页面元素的定位,如果该上传文件功能的html类型为input,例如: <input type="file" name="upload"> 以上类型的上传文件功能吗,我们可以直接使用selenium中的元素定位+send_keys()方法,括号内传入文件路径,例如: driver.find_element

李二狗的博客 5531

java实现文件上传功能详解

javaweb文件上传功能详解

于歌852的标题 1万+

Vue3 实现文件上传功能

【代码】Vue3 实现文件上传功能。

Made In SQL 2094

通过xhr实现文件上传功能,使用jQuery实现文件上传功能

通过xhr实现文件上传功能,使用jQuery实现文件上传功能

背心的博客 2084
上一篇: 超详细的实现下载功能教程,文件下载实现。
下一篇: 【Java】线程的理解和使用
Microanswer
博客等级 码龄10年 38粉丝 40原创
评论 2
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值