SpringBoot整合MinIO实现文件上传的方法详解

目录
  • 前言
  • 1. MinIO 简介
  • 2. MinIO 安装
  • 3. 整合 Spring Boot
  • 4. 配置nginx
  • 5. 小结

前言

现在 OSS 服务算是一个基础服务了,很多云服务厂商都有提供这样的服务,价格也不贵,松哥自己的网站用的就是类似的服务。

不过对于中小公司来说,除了购买 OSS 服务之外,也可以自己搭建专业的文件服务器,自己搭建专门的文件服务器的话,曾经比较专业的做法是 FastDFS,松哥之前也专门为之录过视频发在 B 站上,感兴趣的小伙伴可以自行查看。不过 FastDFS 搭建比较麻烦,非常容易出错,所以对各位小伙伴来说多多少少有一点门槛。

松哥在之前的文章录制的一些项目视频中,如果涉及到文件上传,基本上都是保存在项目本地,这种方式比较省事,但是安全性不高。

所以,今天给大伙介绍一个较好的玩意 MinIO,看看这个工具带给我们什么惊喜。

1. MinIO 简介

MinIO 是一个基于 Apache License v2.0 开源协议的对象存储服务,它兼容亚马逊 S3 云存储服务接口,非常适合于存储大容量非结构化的数据,例如图片、视频、日志文件、备份数据和容器/虚拟机镜像等,而一个对象文件可以是任意大小,从几 KB 到最大 5T 不等。

MinIO 是一个非常轻量的服务,可以很简单的和其他应用的结合,类似 NodeJS, Redis 或者 MySQL。

简单来说,可以使用 MinIO 来搭建一个对象存储服务,而且 MinIO 的 Java 客户端和亚马逊的 S3 云存储服务客户端接口兼容,换句话说,你会往 MinIO 上存数据,就会往 S3 上存数据。

MinIO 的特点:

  • 兼容 Amazon S3:可以使用 MinIO SDK,MinIO Client,AWS SDK 和 AWS CLI 访问 MinIO 服务器。
  • 较强的数据保护能力:MinIO 使用 Minio Erasure Code 来防止硬件故障。
  • 高度可用:MinIO 服务器可以容忍分布式设置中高达(N/2)-1 节点故障。
  • 支持 Lambda 计算。
  • 具有加密和防篡改功能:MinIO 为加密数据提供了机密性,完整性和真实性保证,而且性能开销微乎其微。使用 AES-256-GCM,ChaCha20-Poly1305 和 AES-CBC 支持服务器端和客户端加密。
  • 可对接后端存储:除了 MinIO 自己的文件系统,还支持 DAS、 JBODs、NAS、Google 云存储和 Azure Blob 存储。

2. MinIO 安装

不废话了,赶紧装一个体验一把吧。

为了省事,咱们就直接用 docker 来安装吧

我们执行如下命令,安装 MinIO:

docker run -p 9000:9000 -p 9001:9001 -d minio/minio server /data --console-address ":9000" --address ":9001"

这个启动命令中配置了两个端口:console-address 是后台管理的网页端口;address 则是 API 通信端口。以上面的启动脚本为例,项目启动成功后,网页上的访问端口是 9000,如果我们通过 Java 代码上传文件,通信端口则是 9001。

项目启动成功后,浏览器地址栏输入 http://127.0.0.1:9000/login 即可访问到 MinIO 的后端页面:

默认的登录用户名和密码均为 minioadmin

登录成功之后,我们首先创建一个 bucket,将来我们上传的文件都处于 bucket 之中,如下:

创建成功之后,我们还需要设置一下桶的读取权限,确保文件将来上传成功之后可以读取到,点击左上角的设置按钮进行设置,如下:

设置完成后,接下来我们就可以往这个桶中上传资源了,如下图:

上传完成后,就可以看到刚刚上传的文件了:

上传成功后,点击文件,然后点击右边的 Share 按钮会弹出来文件的访问链接,由于我们已经设置了文件可读,因此可以不用管这里的链接有效期了,直接通过路径的前面部分就可以访问到刚刚上传的图片了,如下:

现在文件就可上传可访问了。是不是比 FastDFS 容易多了!

不过前面这种安装方式其实有点小问题,因为我们没有为 docker 容器设置数据卷,所以如果你把 docker 容器不小心删除了,那么数据也就没了!

所以我们要设置数据卷。

修正后的 docker 脚本如下:

docker run -p 9000:9000 -p 9001:9001 -d --name minio -v /Users/sang/minio/data:/data -v /Users/sang/minio/config:/root/.minio -e "MINIO_ROOT_USER=javaboy" -e "MINIO_ROOT_PASSWORD=123@45678" minio/minio server /data --console-address ":9000" --address ":9001"

主要是加了数据卷映射功能,将 MinIO 的数据和配置文件映射到宿主机上,这样将来即使容器删除了,数据也都还在。

注意上面也自定义了登录用户名和密码。

按照上面的命令,重新创建容器之后,我们也创建一个桶并上传文件,上传成功之后,我们就可以在本地对应的文件夹看到我们上传的文件,如下:

3. 整合 Spring Boot

接下来我们再来看看在 Spring Boot 中如何玩 MinIO。

首先我们创建一个 Spring Boot 项目,引入 Web 依赖,如下:

项目创建成功之后,我们再来手动添加一下 MinIO 的依赖,如下:

<dependency>
    <groupId>io.minio</groupId>
    <artifactId>minio</artifactId>
    <version>8.2.1</version>
</dependency>

这里我尝试用了最新的版本,但是似乎有一些 BUG,我也没有深究,就换了 8.2.1 这个版本,这个版本是 OK 的。

接下来我们来配置一下 application.yaml,配置一下文件上传所需要的基本信息:

minio:
  endpoint: http://localhost:9001
  accessKey: javaboy
  secretKey: 123@45678
  nginxHost: http://local.javaboy.org:9001

这里四个属性:

endpoint:这是 MinIO 的 API 通信地址。

accessKey 和 secretKey 是通信的用户名和密码,这跟网页上登录时候的用户名密码一致。

nginxHost:这个配置用来生成上传文件的访问路径。对于这个路径,有的小伙伴可能会有疑问,nginxHost 不就是 endpoint 吗?为什么还要单独配置?因为对于文件服务器而言,我们上传文件是通过 MinIO,但是访问的时候不一定通过 MinIO,我们可能会自己搭建一个 Nginx 服务器,通过 Nginx 服务器来访问上传后的资源,大家知道 Nginx 非常擅长于做这个事情,效率非常高。所以这里的 nginxHost 其实是指 Nginx 的访问路径。

接下来我们提供一个 MinioProperties 来接收这里的四个属性,如下:

@ConfigurationProperties(prefix = "minio")
public class MinioProperties {
    /**
     * 连接地址
     */
    private String endpoint;
    /**
     * 用户名
     */
    private String accessKey;
    /**
     * 密码
     */
    private String secretKey;
    /**
     * 域名
     */
    private String nginxHost;

    public String getEndpoint() {
        return endpoint;
    }

    public void setEndpoint(String endpoint) {
        this.endpoint = endpoint;
    }

    public String getAccessKey() {
        return accessKey;
    }

    public void setAccessKey(String accessKey) {
        this.accessKey = accessKey;
    }

    public String getSecretKey() {
        return secretKey;
    }

    public void setSecretKey(String secretKey) {
        this.secretKey = secretKey;
    }

    public String getNginxHost() {
        return nginxHost;
    }

    public void setNginxHost(String nginxHost) {
        this.nginxHost = nginxHost;
    }
}

将 application.yaml 中相关的配置注入到这个配置类中来。

接下来我们需要提供一个 MinIOClient,通过这个客户端工具可以操作 MinIO,如下:

@Configuration
@EnableConfigurationProperties(MinioProperties.class)
public class MinioConfig {

    @Autowired
    private MinioProperties minioProperties;

    /**
     * 获取MinioClient
     */
    @Bean
    public MinioClient minioClient() {
        return MinioClient.builder()
                .endpoint(minioProperties.getEndpoint())
                .credentials(minioProperties.getAccessKey(), minioProperties.getSecretKey())
                .build();
    }

}

这个也没啥好说的,传入通信地址以及用户名密码,就可以构建出一个 MinioClient 出来。

当文件上传成功之后,我们可以通过 MinIO 去访问,也可以通过 Nginx 访问,所以接下来我们就需要提供一个类,来封装这两个地址:

public class UploadResponse {
    private String minIoUrl;

    private String nginxUrl;

    public UploadResponse() {
    }

    public UploadResponse(String minIoUrl, String nginxUrl) {
        this.minIoUrl = minIoUrl;
        this.nginxUrl = nginxUrl;
    }

    public String getMinIoUrl() {
        return minIoUrl;
    }

    public void setMinIoUrl(String minIoUrl) {
        this.minIoUrl = minIoUrl;
    }

    public String getNginxUrl() {
        return nginxUrl;
    }

    public void setNginxUrl(String nginxUrl) {
        this.nginxUrl = nginxUrl;
    }
}

再来提供一个 MinIO 文件上传工具类:

@Component
public class MinioUtil {

    @Autowired
    private MinioProperties minioProperties;

    @Autowired
    private MinioClient client;

    /**
     * 创建bucket
     */
    public void createBucket(String bucketName) throws Exception {
        if (!client.bucketExists(BucketExistsArgs.builder().bucket(bucketName).build())) {
            client.makeBucket(MakeBucketArgs.builder().bucket(bucketName).build());
        }
    }

    /**
     * 上传文件
     */
    public UploadResponse uploadFile(MultipartFile file, String bucketName) throws Exception {
        //判断文件是否为空
        if (null == file || 0 == file.getSize()) {
            return null;
        }
        //判断存储桶是否存在  不存在则创建
        createBucket(bucketName);
        //文件名
        String originalFilename = file.getOriginalFilename();
        //新的文件名 = 存储桶文件名_时间戳.后缀名
        assert originalFilename != null;
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
        String fileName = bucketName + "_" +
                System.currentTimeMillis() + "_" + format.format(new Date()) + "_" + new Random().nextInt(1000) +
                originalFilename.substring(originalFilename.lastIndexOf("."));
        //开始上传
        client.putObject(
                PutObjectArgs.builder().bucket(bucketName).object(fileName).stream(
                        file.getInputStream(), file.getSize(), -1)
                        .contentType(file.getContentType())
                        .build());
        String url = minioProperties.getEndpoint() + "/" + bucketName + "/" + fileName;
        String urlHost = minioProperties.getNginxHost() + "/" + bucketName + "/" + fileName;
        return new UploadResponse(url, urlHost);
    }

    /**
     * 获取全部bucket
     *
     * @return
     */
    public List<Bucket> getAllBuckets() throws Exception {
        return client.listBuckets();
    }

    /**
     * 根据bucketName获取信息
     *
     * @param bucketName bucket名称
     */
    public Optional<Bucket> getBucket(String bucketName) throws IOException, InvalidKeyException, NoSuchAlgorithmException, InsufficientDataException, InvalidResponseException, InternalException, ErrorResponseException, ServerException, XmlParserException, ServerException {
        return client.listBuckets().stream().filter(b -> b.name().equals(bucketName)).findFirst();
    }

    /**
     * 根据bucketName删除信息
     *
     * @param bucketName bucket名称
     */
    public void removeBucket(String bucketName) throws Exception {
        client.removeBucket(RemoveBucketArgs.builder().bucket(bucketName).build());
    }

    /**
     * 获取⽂件外链
     *
     * @param bucketName bucket名称
     * @param objectName ⽂件名称
     * @param expires    过期时间 <=7
     * @return url
     */
    public String getObjectURL(String bucketName, String objectName, Integer expires) throws Exception {
        return client.getPresignedObjectUrl(GetPresignedObjectUrlArgs.builder().bucket(bucketName).object(objectName).expiry(expires).build());
    }

    /**
     * 获取⽂件
     *
     * @param bucketName bucket名称
     * @param objectName ⽂件名称
     * @return ⼆进制流
     */
    public InputStream getObject(String bucketName, String objectName) throws Exception {
        return client.getObject(GetObjectArgs.builder().bucket(bucketName).object(objectName).build());
    }

    /**
     * 上传⽂件
     *
     * @param bucketName bucket名称
     * @param objectName ⽂件名称
     * @param stream     ⽂件流
     * @throws Exception https://docs.minio.io/cn/java-client-api-reference.html#putObject
     */
    public void putObject(String bucketName, String objectName, InputStream stream) throws
            Exception {
        client.putObject(PutObjectArgs.builder().bucket(bucketName).object(objectName).stream(stream, stream.available(), -1).contentType(objectName.substring(objectName.lastIndexOf("."))).build());
    }

    /**
     * 上传⽂件
     *
     * @param bucketName  bucket名称
     * @param objectName  ⽂件名称
     * @param stream      ⽂件流
     * @param size        ⼤⼩
     * @param contextType 类型
     * @throws Exception https://docs.minio.io/cn/java-client-api-reference.html#putObject
     */
    public void putObject(String bucketName, String objectName, InputStream stream, long
            size, String contextType) throws Exception {
        client.putObject(PutObjectArgs.builder().bucket(bucketName).object(objectName).stream(stream, size, -1).contentType(contextType).build());
    }

    /**
     * 获取⽂件信息
     *
     * @param bucketName bucket名称
     * @param objectName ⽂件名称
     * @throws Exception https://docs.minio.io/cn/java-client-api-reference.html#statObject
     */
    public StatObjectResponse getObjectInfo(String bucketName, String objectName) throws Exception {
        return client.statObject(StatObjectArgs.builder().bucket(bucketName).object(objectName).build());
    }

    /**
     * 删除⽂件
     *
     * @param bucketName bucket名称
     * @param objectName ⽂件名称
     * @throws Exception https://docs.minio.io/cn/java-client-apireference.html#removeObject
     */
    public void removeObject(String bucketName, String objectName) throws Exception {
        client.removeObject(RemoveObjectArgs.builder().bucket(bucketName).object(objectName).build());
    }
}

都是一些常规的 API 调用,我就不逐行解释了,接下来我们来一个文件上传接口:

@RestController
public class FileUploadController {
    @Autowired
    MinioUtil minioUtil;

    @PostMapping("/upload")
    public String fileUpload(MultipartFile file) throws Exception {
        UploadResponse bucket01 = minioUtil.uploadFile(file, "bucket01");
        System.out.println("bucket01.getMinIoUrl() = " + bucket01.getMinIoUrl());
        System.out.println("bucket01.getNginxUrl() = " + bucket01.getNginxUrl());
        return bucket01.getMinIoUrl();
    }
}

好啦,大功告成。

接下来启动 Spring Boot 项目,然后调用这个接口上传文件,上传成功后,控制台会打印如下信息:

这就表示文件上传成功了。

4. 配置nginx

前面提到了 MinIO 可以结合 Nginx 来使用,那我们这里就来配一配 Nginx 看看。

为了省事,Nginx 我也选择安装到 docker 容器中,但是前面安装 MinIO 时,我们已经做了数据卷映射,即上传到 MinIO 的文件实际上是保存在宿主机的,所以现在也得给 Nginx 配置数据卷,将来让 Nginx 也去 /Users/sang/minio/data 路径下查找文件。

Nginx 安装指令如下:

docker run --name nginx01 -p 8888:80 -v /Users/sang/minio/data:/usr/share/nginx/html:ro -d nginx

这里两个关键点:

  • 设置 Nginx 端口为 8888。
  • 将 MinIO 映射到宿主机的数据卷,再次挂载到 Nginx 上去。

大家知道,默认情况下,当我们访问 Nginx 的时候,Nginx 给我们展示出来的数据其实就是 /usr/share/nginx/html 目录下的,现在该目录其实就相当于我宿主机的 /Users/sang/minio/data 目录,所以我现在都不用修改 Nginx 的配置了,装好之后直接使用 Nginx 即可。

好啦,接下来我们修改一下 application.yaml,如下:

minio:
  endpoint: http://localhost:9001
  accessKey: javaboy
  secretKey: 123@45678
  nginxHost: http://local.javaboy.org:8888

改完之后,再次上传文件,此时打印出来的文件访问路径如下:

现在我们通过这个 Nginx 路径也能访问到刚刚上传的文件了。

5. 小结

今天就和小伙伴们分享一下 MinIO 的用法,并结合 Nginx 搭建了一个简单的文件服务器。

到此这篇关于SpringBoot整合MinIO实现文件上传的方法详解的文章就介绍到这了,更多相关SpringBoot MinIO文件上传内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • springboot 使用 minio的示例代码

    什么是MinIo MinIO 是一个基于Apache License v2.0开源协议的对象存储服务.它兼容亚马逊S3云存储服务接口,非常适合于存储大容量非结构化的数据,例如图片.视频.日志文件.备份数据和容器/虚拟机镜像等,而一个对象文件可以是任意大小,从几kb到最大5T不等.MinIO是一个非常轻量的服务,可以很简单的和其他应用的结合,类似 NodeJS, Redis 或者 MySQL. Minio主要用来存储非结构化的数据,类似文件,图片,照片,日志文件,各类备份文件等,按照官网描述,文件

  • Springboot集成minio实现文件存储的实现代码

    目录 1.安装部署 1.1Linux简单部署 1.2Docker部署 2.Springboot整合 3.问题记录 4.项目地址 在我们平时做项目的时候,文件存储是个很常见的需求.这时候我们就会用到对象存储服务,平时我们可能会选择OSS.AWS S3这类第三方服务.今天带大家搭建一款自己的对象存储服务,带可视化管理,用起来也挺简单. MinIO 是一款基于Go语言的高性能对象存储服务,它采用了Apache License v2.0开源协议,非常适合于存储大容量非结构化的数据,例如图片.视频.日志文

  • springboot整合minio实现文件上传与下载且支持链接永久访问

    目录 1.minio部署 2.项目搭建 3.文件上传 4.文件下载 5.文件永久链接下载 1.minio部署 1.1 拉取镜像 docker pull minio/minio 1.2 创建数据目录 mkdir -p /home/guanz/minio mkdir -p /home/guanz/minio/midata 1.3 启动minio docker run -d -p 9000:9000 -p 9001:9001 --restart=always -e MINIO_ACCESS_KEY=g

  • SpringBoot使用minio及配置代码

    目录 1.导入 minio jar包 2.配置 3.实现 MinIO是一个开源的对象存储服务.适合于存储大容量非结构化的数据,例如图片.视频.日志文件.备份数据和容器/虚拟机镜像等,而一个对象文件可以是任意大小,从几kb到最大5T不等. MinIO是一个非常轻量的服务,可以很简单的和其他应用的结合,类似 NodeJS, Redis 或者 MySQL. 1.导入 minio jar包 <dependency> <groupId>io.minio</groupId> <

  • SpringBoot2 整合MinIO中间件实现文件便捷管理功能

    本文源码:GitHub·点这里 || GitEE·点这里 一.MinIO简介 1.基础描述 MinIO是一个开源的对象存储服务.适合于存储大容量非结构化的数据,例如图片.视频.日志文件.备份数据和容器/虚拟机镜像等,而一个对象文件可以是任意大小,从几kb到最大5T不等. MinIO是一个非常轻量的服务,可以很简单的和其他应用的结合,类似 NodeJS, Redis 或者 MySQL. 2.存储机制 MinIO使用按对象的嵌入式擦除编码保护数据,该编码以汇编代码编写,可提供最高的性能.MinIO使

  • 手把手教你SpringBoot轻松整合Minio

    前言 使用Spring Boot 可以非常方便.快速搭建项目,使我们不用关心框架之间的兼容性,适用版本等各种问题,我们想使用任何东西,仅仅添加一个配置就可以. 提示:以下是本篇文章正文内容,下面案例可供参考 一.技术介绍 1.Minio是什么? MinIO 是一个基于Apache License v2.0开源协议的对象存储服务.它兼容亚马逊S3云存储服务接口,非常适合于存储大容量非结构化的数据,例如图片.视频.日志文件.备份数据和容器/虚拟机镜像等,而一个对象文件可以是任意大小,从几kb到最大5

  • SpringBoot整合MinIO实现文件上传的方法详解

    目录 前言 1. MinIO 简介 2. MinIO 安装 3. 整合 Spring Boot 4. 配置nginx 5. 小结 前言 现在 OSS 服务算是一个基础服务了,很多云服务厂商都有提供这样的服务,价格也不贵,松哥自己的网站用的就是类似的服务. 不过对于中小公司来说,除了购买 OSS 服务之外,也可以自己搭建专业的文件服务器,自己搭建专门的文件服务器的话,曾经比较专业的做法是 FastDFS,松哥之前也专门为之录过视频发在 B 站上,感兴趣的小伙伴可以自行查看.不过 FastDFS 搭

  • 利用PHP POST临时文件机制实现任意文件上传的方法详解

    目录 原理 如何获取临时文件名 $_FILES phpinfo glob 如何利用该文件 组合请求 延长临时文件存在时间 参考 原理 向 PHP 发送 Post 数据包,如果数据包中包含文件,无论 php 代码中有没有处理文件上传的逻辑,php 都会将这个文件保存为一个临时文件 该文件默认存储在 /tmp 目录中『可通过 php.ini 的 upload_tmp_dir 指定存储位置』 文件名为 php[6个随机字符],例:phpG4ef0q 若本次请求正常结束,临时文件会被自动删除 若非正常结

  • SpringBoot整合MongoDB实现文件上传下载删除

    本文主要内容 MongoDB基础操作命令示例练习 MongoDB居于GridFSTemplate的文件上传.下载.删除等操作(工作重点使用) 1. 基础命令 创建的数据库名称:horse,创建的集合名称:blog # 创建数据库 use horse # 删除当前数据库[horse] db.dropDatebase() # 查看所有数据库 show dbs # 设置用户的角色和权限 db.createUser({user:"horse",pwd:"mongo123",

  • springboot整合阿里云oss上传的方法示例

    OSS申请和配置 1. 注册登录 输入网址:https://www.aliyun.com/product/oss 如果没有账号点击免费注册,然后登录. 2.开通以及配置 点击立即开通 进入管理控制台 第一次使用会出现引导,按引导点击"我知道了",然后点击创建Bucket. 如果没有存储包或流量包点击购买. 点击确定,返回主页面,出现该页面,点击我知道了 将EndPoint记录下来,方便后期添加到我们项目的配置文件中 创建 AccessKeyID 和 AccessKeySecret 点击

  • SpringBoot拦截器与文件上传实现方法与源码分析

    目录 一.拦截器 1.创建一个拦截器 2.配置拦截器 二.拦截器原理 三.文件上传 四.文件上传流程 一.拦截器 拦截器我们之前在springmvc已经做过介绍了 大家可以看下[SpringMVC]自定义拦截器和过滤器 为什么在这里还要再讲一遍呢? 因为spring boot里面对它做了简化,大大节省了我们配置那些烦人的xml文件的时间 接下来,我们就通过一个小例子来了解一下拦截器在spring boot中的使用 1.创建一个拦截器 首先我们创建一个拦截器,实现HandlerIntercepto

  • SpringBoot实现项目文件上传的方法详解

    目录 一.首先抛出问题 二.解决思路 三.直接看源码就懂了,下面是controller 四.结尾 一.首先抛出问题 以阿里云oss文件上传为例,假设我的需求是这样的,我需要发布一条动态,这条动态呢可以是图片.语音.视频,3种类型,每种类型的上传我必须要限制它的文件大小,超过了我就不能让他上传的.如果传统的方式,那就是创建3个上传类型bucket对应图片.语音和视频,其实这种做法是可以的,但是怎么说呢,还不够优雅,如果当这个动态有越来越多种类型,你是不是要建立N个类型对应呢,所以就会使得bucke

  • Bootstrap Fileinput文件上传组件用法详解

    最近时间空余,总结了一些关于bootstrap fileinput组件的一些常见用法,特此分享到我们平台,供大家参考,同时也方便以后的查找.本文写的不好还请见谅. 一.效果展示 1.原始的input type='file',简直不忍直视. 2.不做任何装饰的bootstrap fileinput:(bootstrap fileinput初级进化) 3.bootstrap fileinput高级进化:中文化.可拖拽上传.文件扩展名校验(如果不是需要的文件,不让上传) 拖拽上传 上传中 4.boot

  • Java 文件上传的实例详解

    Java 文件上传的实例详解 java 文件上传 Java文件上传,介绍几种常用的方法,也是经过本人亲手调试过的 1.jspsmartupload 这个组件用起来是挺方便的,不过就是只适合小文件上传,如果大文件上传的话就不行,查看了一下他的代码,m_totalBytes = m_request.getContentLength(); m_binArray = new byte[m_totalBytes];居然把整个上传文件都读到内存去了,那如果是上传几十M的文件,同时几个用户上传,服务器稳挂,不

  • 最详细的文件上传下载实例详解(推荐)

    在Web应用系统开发中,文件上传和下载功能是非常常用的功能,今天来讲一下JavaWeb中的文件上传和下载功能的实现. 对于文件上传,浏览器在上传的过程中是将文件以流的形式提交到服务器端的,如果直接使用Servlet获取上传文件的输入流然后再解析里面的请求参数是比较麻烦,所以一般选择采用apache的开源工具common-fileupload这个文件上传组件.这个common-fileupload上传组件的jar包可以去apache官网上面下载,也可以在struts的lib文件夹下面找到,stru

随机推荐