一、项目信息说明

minio Server版本:linux-amd64/minio 与 windows-amd64/minio.exe
minio Client版本:linux-amd64/mc 与 windows-amd64/mc.exe
minio sdk: https://dl.min.io/sdk/minio-java/

官方文档:MinIO Client (mc) — MinIO祼机使用文档

MinIO Server — MinIO祼机使用文档

二、使用说明

1.使用体验

单机部署简单,使用一条指令即可启动、配置服务器节点(服务器地址,端口、api端口)minio服务,自带页面。
mc客户端有详细中文文档,api调用接口简易

支持生命周期管理(支持日期与天数、支持设置桶内文件夹),设置后,文件会根据规则自动删除源文件

2.大体工作流程

minioServer部署—>mc客户端/api接口创建存储桶---->mc客户端/api接口配置生命周期规则—>minio页面/api接口存储文件—>minio页面/api接口获取文件或文件url

三、minio Server部署

1.启动服务

linux:

./minio server /data/minio  --address ip:api调用端口  --console-address ip:服务器端口 --config-dir 配置文件地址

window:

.\minio.exe server D:\Utils\minio\  --address ip:api调用端口  --console-address ip:服务器端口 --config-dir 配置文件地址


2.配置

minIO server在默认情况下会将所有配置信息存到 ${HOME}/.minio/config.json 文件中。 可用--config-dir在启动服务时重写

# 设置用户名
set MINIO_ACCESS_KEY=minioadmin
# 设置密码(8位)
set MINIO_SECRET_KEY=minioadmin
3.证书目录

TLS证书存在${HOME}/.minio/certs目录下,你需要将证书放在该目录下来启用HTTPS 。如果你是一个乐学上进的好青年,这里有一本免费的秘籍传授一你: 如何使用TLS安全的访问minio.

以下是一个带来TLS证书的MinIO server的目录结构。

Copy$ tree ~/.minio
/home/user1/.minio
├── certs
│   ├── CAs
│   ├── private.key
│   └── public.crt
└── config.json

四、MinIO Client使用

MinIO Client 简称mc,是minio服务器的客户端,对ls,cat,cp,mirror,diff,find等UNIX命令提供了一种替代方案,它支持文件系统和兼容Amazon S3的云存储服务(AWS Signature v2和v4)。

1.mc指令

ls 列出文件和文件夹。
mb 创建一个存储桶或一个文件夹。
cat 显示文件和对象内容。
pipe 将一个STDIN重定向到一个对象或者文件或者STDOUT。
share 生成用于共享的URL。
cp 拷贝文件和对象。
mirror 给存储桶和文件夹做镜像。
find 基于参数查找文件。
diff 对两个文件夹或者存储桶比较差异。
rm 删除文件和对象。
events 管理对象通知。
watch 监听文件和对象的事件。
policy 管理访问策略。
session 为cp命令管理保存的会话。
config 管理mc配置文件。
update 检查软件更新。
version 输出版本信息。

2.常用命令
//设置        别名  api地址    用户名      密码
mc alias set ALIAS HOSTNAME ACCESSKEY SECRETKEY
//列出指定桶的当前生命周期管理规则
mc ilm list TARGET [FLAGS]//添加新的存储桶生命周期管理规则
mc ilm add TARGET [FLAGS]
// 使用 mc ilm add 和 --expiry-days 到 在对象创建数天后使存储桶内容过期:
mc ilm add ALIAS/PATH --expiry-days "DAYS"
//使用 mc ilm remove 删除存储桶生命周期管理规则
mc ilm remove --id "RULE" ALIAS/PATH

五、MINIO SDK(Java) Java Client API参考文档 | Minio中文文档

1.导入
<!--maven--><dependency><groupId>io.minio</groupId><artifactId>minio</artifactId><version>8.4.1</version><exclusions><exclusion><groupId>com.squareup.okhttp3</groupId><artifactId>okhttp</artifactId></exclusion></exclusions></dependency>
<!--minio的okhttp有可能会报错--><dependency><groupId>com.squareup.okhttp3</groupId><artifactId>okhttp</artifactId><version>4.9.0</version></dependency></dependencies>
<!--gradle-->
dependencies {compile 'io.minio:minio:8.4.1'
}
2.配置
#minio
minio:url: http://10.10.18.178:9000accessKey: minioadminsecretKey: minioadminbucketName: bucket-test01#分区上传文件大小partSize: 104857600
import cn.akeparking.middleware.service.minio.MinioTemplate;
import io.minio.MinioClient;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;@Data
@Configuration
@ConfigurationProperties(prefix = "minio")
public class MinIoConfig {/*** 服务地址(服务接口地址)*/private String url;/*** 用户名*/private String accessKey;/*** 密码*/private String secretKey;/*** 存储桶名称*/private String bucketName;private Integer partSize;@Beanpublic MinioTemplate getMinioClient() {return new MinioTemplate(url,accessKey, secretKey,partSize);}
}
3.常用api
1)创建储存桶

通过MinioTemplate.createBucket(bucketName)创建桶,或调用sdk包的minioClient.makeBucket方法

2)设置生命周期

通过MinioTemplate.setBucketExpirationByDays(bucketName,prefix,days,ruleName)创建对应桶的生命周期,prefix对应相应的文件夹,days对应过期天数,ruleName对应文件名称

3)存入文件

通过MinioTemplate.putObject(bucketName,objectName,base64Str/MultipartFile/InputStream)存入文件,实际上皆转为上传

PutObjectArgs putObjectArgs = PutObjectArgs.builder().bucket(bucketName).object(objectName).stream(stream, size, partSize).build();
client.putObject(putObjectArgs);

4)取文件

通过MinioTemplate.getObject(bucketName,objectName)获取对应的文件流,或者通过MinioTemplate.presignedObjectUrl(bucketName,objectName,时间, 时间单位)来获取有期限的文件url

4.工具类
import io.minio.*;
import io.minio.http.Method;
import io.minio.messages.*;
import lombok.AllArgsConstructor;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.multipart.MultipartFile;
import sun.misc.BASE64Decoder;import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.time.ZonedDateTime;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.Optional;
import java.util.concurrent.TimeUnit;@AllArgsConstructor
@Slf4j
public class MinioTemplate {private String endpoint;private String accessKey;private String secretKey;private int partSize;private MinioClient client;@SneakyThrowspublic MinioTemplate(String endpoint, String accessKey, String secretKey, int partSize) {this.endpoint = endpoint;this.accessKey = accessKey;this.secretKey = secretKey;this.partSize = partSize;this.client = MinioClient.builder().endpoint(endpoint).credentials(accessKey, secretKey).build();}/*** 创建bucket** @param bucketName bucket名称*/public void createBucket(String bucketName) throws Exception {if (!client.bucketExists(BucketExistsArgs.builder().bucket(bucketName).build())) {client.makeBucket(MakeBucketArgs.builder().bucket(bucketName).build());}}/**** @param bucketName* @param days* @param ruleName* @throws Exception*/public void setBucketExpirationByDays(String bucketName,String prefix,Integer days,String ruleName) throws Exception{// 获取配置LifecycleConfiguration lifecycleConfiguration =client.getBucketLifecycle(GetBucketLifecycleArgs.builder().bucket(bucketName).build());List<LifecycleRule> rules = lifecycleConfiguration.rules();List<LifecycleRule> rulesNew = new ArrayList<>();rulesNew.addAll(rules);// 配置生命周期规则rulesNew.add(new LifecycleRule(Status.ENABLED, // 开启状态null,new Expiration((ZonedDateTime) null, days, null), // 保存365天new RuleFilter(prefix), // 目录配置ruleName,null,null,null));LifecycleConfiguration lifecycleConfigurationNew = new LifecycleConfiguration(rulesNew);// 添加生命周期配置client.setBucketLifecycle(SetBucketLifecycleArgs.builder().bucket(bucketName).config(lifecycleConfigurationNew).build());}public List<LifecycleRule> getBucketLifecycleRule(String bucketName) throws Exception{// 获取配置LifecycleConfiguration lifecycleConfiguration1111 =client.getBucketLifecycle(GetBucketLifecycleArgs.builder().bucket(bucketName).build());List<LifecycleRule> rules1 = lifecycleConfiguration1111.rules();for (LifecycleRule lifecycleRule:rules1) {log.debug(lifecycleRule.toString());log.debug("Lifecycle status is " + lifecycleRule.status()+"\nLifecycle prefix is " + lifecycleRule.filter().prefix()+"\nLifecycle expiration days is " + lifecycleRule.expiration().days());}return rules1;}/*** 获取全部bucket* <p>* https://docs.minio.io/cn/java-client-api-reference.html#listBuckets*/public List<Bucket> getAllBuckets() throws Exception {return client.listBuckets();}/*** 根据bucketName获取信息* @param bucketName bucket名称*/public Optional<Bucket> getBucket(String bucketName) throws Exception {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 stream 文件流* @param size 文件大小*/public String putObject(String bucketName, String objectName, InputStream stream, Long size) throws Exception{PutObjectArgs putObjectArgs = PutObjectArgs.builder().bucket(bucketName).object(objectName).stream(stream, size, partSize).build();ObjectWriteResponse objectWriteResponse = client.putObject(putObjectArgs);return objectWriteResponse.object();}/*** 根据文件前置查询文件** @param bucketName bucket名称* @param prefix     前缀* @param recursive  是否递归查询* @return MinioItem 列表*/public List<Item> getAllObjectsByPrefix(String bucketName, String prefix, boolean recursive) throws Exception {List<Item> objectList = new ArrayList<>();ListObjectsArgs listObjectsArgs = ListObjectsArgs.builder().bucket(bucketName).prefix(prefix).recursive(recursive).build();Iterable<Result<Item>> objectsIterator = client.listObjects(listObjectsArgs);while (objectsIterator.iterator().hasNext()) {objectList.add(objectsIterator.iterator().next().get());}return objectList;}/*** 获取文件外链* 这里的 method 方法决定最后链接是什么请求获得*  expiry 决定这个链接多久失效* @param bucketName bucket名称* @param objectName 文件名称* @param duration 有效大小* @param* @return url*/public String getObjectURL(String bucketName, String objectName,Integer duration, TimeUnit unit) throws Exception {if (null==duration||null==unit){duration = 7;unit = TimeUnit.DAYS;}GetPresignedObjectUrlArgs args = GetPresignedObjectUrlArgs.builder().bucket(bucketName).method(Method.GET).expiry(duration, unit).object(objectName).build();return client.getPresignedObjectUrl(args);}/*** 获取文件** @param bucketName bucket名称* @param objectName 文件名称* @return 二进制流*/public InputStream getObject(String bucketName, String objectName) throws Exception {GetObjectArgs getObjectArgs = GetObjectArgs.builder().bucket(bucketName).object(objectName).build();return client.getObject(getObjectArgs);}/*** 上传文件 base64* @param bucketName bucket名称* @param objectName 文件名称* @param base64Str 文件base64*/public String putObject(String bucketName, String objectName, String base64Str) throws Exception{InputStream inputStream = new ByteArrayInputStream(base64Str.getBytes());// 进行解码BASE64Decoder base64Decoder = new BASE64Decoder();byte[] byt = new byte[0];try {byt = base64Decoder.decodeBuffer(inputStream);} catch (IOException e) {e.printStackTrace();}inputStream = new ByteArrayInputStream(byt);putObject(bucketName, objectName, inputStream, Long.valueOf(byt.length));return objectName;}/*** 上传文件* @param bucketName bucket名称* @param objectName 文件名称* @param file 文件* @throws Exception*/public String putObject( String bucketName,String objectName, MultipartFile file) throws Exception{this.putObject(bucketName, objectName, file.getInputStream(), file.getSize());return objectName;}/*** 获取文件信息** @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 {StatObjectArgs statObjectArgs = StatObjectArgs.builder().bucket(bucketName).object(objectName).build();return client.statObject(statObjectArgs);}/*** 删除文件** @param bucketName bucket名称* @param objectName 文件名称* @throws Exception https://docs.minio.io/cn/java-client-api-reference.html#removeObject*/public void removeObject(String bucketName, String objectName) throws Exception {RemoveObjectArgs removeObjectArgs = RemoveObjectArgs.builder().bucket(bucketName).object(objectName).build();client.removeObject(removeObjectArgs);}/*** 根据文件名返回对应contentType* @param objectName* @return*/private String getContentType(String objectName) {//if(FileNameUtil.isPicture(objectName)) {//    return "image/jpeg";//}//if(FileNameUtil.isVideo(objectName)) {//    return "video/mp4";//}return null;}/*** 获取直传链接* @param bucketName bucket名称* @param objectName 文件名称* @throws Exception*/public String presignedPutObject( String bucketName,String objectName) throws Exception{GetPresignedObjectUrlArgs getPresignedObjectUrlArgs = GetPresignedObjectUrlArgs.builder().method(Method.PUT).bucket(bucketName).object(objectName).expiry(7, TimeUnit.DAYS).build();return client.getPresignedObjectUrl(getPresignedObjectUrlArgs);}/*** 合并文件* @param bucketName* @param chunkNames* @param targetObjectName* @return* @throws Exception*/public String composeObject(String bucketName, List<String> chunkNames, String targetObjectName) throws Exception{List<ComposeSource> sources = new ArrayList<>(chunkNames.size());for (String chunkName : chunkNames) {ComposeSource composeSource = ComposeSource.builder().bucket(bucketName).object(chunkName).build();sources.add(composeSource);}ComposeObjectArgs composeObjectArgs = ComposeObjectArgs.builder().bucket(bucketName).sources(sources).object(targetObjectName).build();ObjectWriteResponse objectWriteResponse = client.composeObject(composeObjectArgs);return objectWriteResponse.object();}
}

文件上传到minio,获取文件列表,下载文件

minio下载
以下是代码是实现
import com.alibaba.fastjson.JSONObject;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.google.common.io.ByteStreams;
import com.jspxcms.ext.web.utils.PageUtil;
import com.jspxcms.ext.web.vo.FileVo;
import io.minio.MinioClient;
import io.minio.ObjectStat;
import io.minio.PutObjectOptions;
import io.minio.Result;
import io.minio.errors.*;
import io.minio.messages.Bucket;
import io.minio.messages.Item;import org.springframework.http.MediaType;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.multipart.MultipartFile;import javax.servlet.http.HttpServletResponse;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.text.DecimalFormat;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.util.*;@Controller
@RequestMapping("/file")
public class FileUploadController {private static MinioClient minioClient;// minio服务器地址private static final String endpoint = "http://127.0.0.1:9001";static {try {// minioClient初始化,设置endpoint和连接minio服务所需的密码minioClient = new MinioClient(endpoint, "xxx", "xxx");} catch (Exception e) {e.printStackTrace();}}/*** 文件上传** @param file       文件* @param bucketName 文件夹名称(minio上对应的bucket相当于文件夹)* @return* @throws Exception*/@ResponseBody@RequestMapping(value = "/upload", method = RequestMethod.POST, produces = "application/json;charset=UTF-8")public String uploadFile(MultipartFile file, String bucketName) throws Exception {JSONObject res = new JSONObject();// 判断上传文件是否为空if (null == file || 0 == file.getSize()) {return "文件不能为空";}// 判断文件夹是否存在boolean bucketExists = minioClient.bucketExists(bucketName);// 如果文件夹不存在则创建if (!bucketExists) {// 创建minioClient.makeBucket(bucketName);}// 文件名String originalFilename = file.getOriginalFilename();// 上传操作minioClient.putObject(bucketName, originalFilename, file.getInputStream(), new PutObjectOptions(file.getSize(), 0L));return "文件上传成功";}/*** 获取文件列表** @param pageNum  页码* @param pageSize 一页的数量* @return* @throws Exception*/@ResponseBody@RequestMapping(value = "/fileList", method = RequestMethod.GET, produces = "application/json;charset=UTF-8")public String getFileList(Integer pageNum, Integer pageSize) throws Exception {DecimalFormat df = new DecimalFormat("0.00");List<Bucket> buckets = minioClient.listBuckets();List<FileVo> list = new ArrayList<>(32);if (!buckets.isEmpty()) {buckets.forEach(s -> {try {// 得到bucket下的文件Iterable<Result<Item>> results = minioClient.listObjects(s.name());// 循环遍历获取每一个文件对象results.forEach(g -> {try {FileVo fileVo = new FileVo();fileVo.setBucketName(s.name());  // 文件夹名称fileVo.setFileName(g.get().objectName());  // 文件名称fileVo.setUpdateTime(localDateTime2Date(g.get().lastModified().toLocalDateTime()));  // 文件上传时间Long size = g.get().size();if (size > (1024 * 1024)) {fileVo.setFileSize(df.format(((double) size / 1024 / 1024)) + "MB");  // 文件大小,如果超过1M,则把单位换成MB} else if (size > 1024) {fileVo.setFileSize(df.format(((double) size / 1024)) + "KB"); // 文件大小,如果没超过1M但是超过1000字节,则把单位换成KB} else {fileVo.setFileSize( size + "bytes");  // // 文件大小,如果没超过1000字节,则把单位换成bytes}list.add(fileVo);} catch (ErrorResponseException e) {e.printStackTrace();} catch (InsufficientDataException e) {e.printStackTrace();} catch (InternalException e) {e.printStackTrace();} catch (InvalidBucketNameException e) {e.printStackTrace();} catch (InvalidKeyException e) {e.printStackTrace();} catch (InvalidResponseException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();} catch (NoSuchAlgorithmException e) {e.printStackTrace();} catch (XmlParserException e) {e.printStackTrace();}});} catch (XmlParserException e) {e.printStackTrace();}});}JSONObject res = new JSONObject();res.put("code", 200);res.put("message", "获取文件列表成功");// 按最后上传时间排序list.sort(new Comparator<FileVo>() {@Overridepublic int compare(FileVo o1, FileVo o2) {return o2.getUpdateTime().compareTo(o1.getUpdateTime());}});// 分页List returnList = PageUtil.startPage(list, pageNum, pageSize);res.put("list", returnList);ObjectMapper mapper = new ObjectMapper();String s = mapper.writeValueAsString(res);return s;}/*** 文件下载(浏览器端下载)** @param bucketName 文件夹名称* @param filetName  文件名称* @param response* @throws Exception*/@ResponseBody@RequestMapping(value = "/download", method = RequestMethod.GET)public void download(String bucketName, String filetName, HttpServletResponse response) throws Exception {// 根据文件夹名称和文件名称找到对应文件对象ObjectStat stat = minioClient.statObject(bucketName, filetName);byte[] buffer = new byte[1024];int length = (int) stat.length();try (InputStream inputStream = minioClient.getObject(bucketName, filetName);ByteArrayOutputStream outputStream = new ByteArrayOutputStream(length)) {ByteStreams.copy(inputStream, outputStream);buffer = outputStream.toByteArray();} catch (Exception e) {e.printStackTrace();}response.setContentType(MediaType.APPLICATION_OCTET_STREAM_VALUE);response.setHeader("Content-disposition", "attachment; filename=" + new String(filetName.getBytes("utf-8"), "ISO8859-1"));response.getOutputStream().write(buffer);response.flushBuffer();response.getOutputStream().close();}/*** 删除文件** @param bucketName 文件夹名称* @param filetName  文件名称* @return* @throws Exception*/@ResponseBody@RequestMapping(value = "/remove", method = RequestMethod.POST, produces = "application/json;charset=UTF-8")public JSONObject removeFile(String bucketName, String filetName) throws Exception {// 删除文件夹下的对应文件minioClient.removeObject(bucketName, filetName);JSONObject res = new JSONObject();res.put("code", 200);res.put("message", "删除文件成功");return res;}/*** 删除文件夹** @param bucketName 文件夹名称* @return* @throws Exception*/@ResponseBody@RequestMapping(value = "/delete.do", method = RequestMethod.POST, produces = "application/json;charset=UTF-8")public JSONObject removeBucket(String bucketName) throws Exception {// 删除文件夹minioClient.removeBucket(bucketName);JSONObject res = new JSONObject();res.put("code", 200);res.put("message", "删除文件夹成功");return res;}/*** LocalDateTime转换为Date* @param localDateTime*/public Date localDateTime2Date( LocalDateTime localDateTime){ZoneId zoneId = ZoneId.systemDefault();ZonedDateTime zdt = localDateTime.atZone(zoneId);Date date = Date.from(zdt.toInstant());Calendar cal=Calendar.getInstance();cal.setTime(date);// 由于获取的时间存在时间差,我这里手动加上16小时cal.add(Calendar.HOUR_OF_DAY, 16);date = cal.getTime();return date;}}
FileVo
package com.jspxcms.ext.web.vo;import com.fasterxml.jackson.annotation.JsonFormat;import java.util.Date;public class FileVo {private String bucketName;    //  文件夹private String fileName;    // 文件名@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")private Date updateTime;   // 最后修改时间private String fileSize;   //  文件大小public String getBucketName() {return bucketName;}public void setBucketName(String bucketName) {this.bucketName = bucketName;}public String getFileName() {return fileName;}public void setFileName(String fileName) {this.fileName = fileName;}public Date getUpdateTime() {return updateTime;}public void setUpdateTime(Date updateTime) {this.updateTime = updateTime;}public String getFileSize() {return fileSize;}public void setFileSize(String fileSize) {this.fileSize = fileSize;}
}
附上分页工具类
package com.jspxcms.ext.web.utils;import java.util.List;/*** 自定义分页工具*/
public class PageUtil {/*** 开始分页* @param list  需要进行分页的集合列表* @param pageNum 页码* @param pageSize 每页多少条数据* @return*/public static List startPage(List list, Integer pageNum,Integer pageSize) {if (list == null) {return null;}if (list.size() == 0) {return null;}if(null == pageNum || "".equals(pageNum.toString())){pageNum = 1;}if(null == pageSize || "".equals(pageSize.toString())){pageSize = 10;}Integer count = list.size(); // 记录总数Integer pageCount = 0; // 页数if (count % pageSize == 0) {pageCount = count / pageSize;} else {pageCount = count / pageSize + 1;}int fromIndex = 0; // 开始索引int toIndex = 0; // 结束索引if (pageNum != pageCount) {fromIndex = (pageNum - 1) * pageSize;toIndex = fromIndex + pageSize;} else {fromIndex = (pageNum - 1) * pageSize;toIndex = count;}List pageList = list.subList(fromIndex, toIndex);return pageList;}
}

MINIO使用说明(附文件上传下载)相关推荐

  1. 微信小程序开发之文件上传下载应用场景(附Demo源码)

    微信小程序开发之文件上传下载应用场景(附Demo源码),Demo为小相册应用,源码在附件中,本示例需要腾讯云支持. http://www.henkuai.com/forum.php?mod=viewt ...

  2. 【Java编程系列】Minio实现文件上传下载

    热门系列: [Java编程系列]Amazon S3实现文件上传下载 目录 热门系列: 1.前言 2.Minio实战代码 2.1 Minio环境部署 2.2 Minio的Sdk对接实现 2.2.1 Mi ...

  3. C++:FTP文件上传下载(附完整源码)

    C++:FTP文件上传下载 FTP文件下载 FTP文件上传 FTP文件下载 #include #include #include #pragma comment(lib, "WinInet. ...

  4. Linux和windows下minio+springboot实现文件服务器上传下载和nginx反向代理

    1 minio服务器的安装 在下载minio.exe文件: windows安装minio服务器:MinIO | Code and downloads to create high performanc ...

  5. 教你如何实现c#文件上传下载功能

    简单介绍一下c#文件上传下载功能实现. NuGet 安装SqlSugar Model文件下新建 DbContext 类 public class DbContext {public DbContext ...

  6. [C# 网络编程系列]专题十一:实现一个基于FTP协议的程序——文件上传下载器...

    引言: 在这个专题将为大家揭开下FTP这个协议的面纱,其实学习知识和生活中的例子都是很相通的,就拿这个专题来说,要了解FTP协议然后根据FTP协议实现一个文件下载器,就和和追MM是差不多的过程的,相信 ...

  7. SpringMVC整合fastdfs-client-java实现web文件上传下载

    为什么80%的码农都做不了架构师?>>>    版权声明:本文为博主原创文章,转载请标明出处(http://blog.csdn.net/wlwlwlwl015)Thanks. 目录( ...

  8. JavaWeb实现文件上传下载功能实例解析

    转:http://www.cnblogs.com/xdp-gacl/p/4200090.html JavaWeb实现文件上传下载功能实例解析 在Web应用系统开发中,文件上传和下载功能是非常常用的功能 ...

  9. 文件上传 java web_JavaWeb 文件上传下载

    1. 文件上传下载概述 1.1. 什么是文件上传下载 所谓文件上传下载就是将本地文件上传到服务器端,从服务器端下载文件到本地的过程.例如目前网站需要上传头像.上传下载图片或网盘等功能都是利用文件上传下 ...

最新文章

  1. SpringBoot + Redis:模拟 10w 人的秒杀抢单!
  2. 换血吃药改基因,硅谷富豪们想用钱收买死神丨视频
  3. Minor GC和Full GC触发条件
  4. c语言printf族函数,C语言中的printf族函数深入详解
  5. php反向解析域名,域名系统 – Cloudflare,反向DNS和php邮件,最终在垃圾邮件文件夹中...
  6. 拓端tecdat|R语言用rle,svm和rpart决策树进行时间序列预测
  7. 第八章 (二)贪心法
  8. java 打印素数_Java 素数打印
  9. python翻译-50 行代码,实现中英文翻译
  10. MAML小样本学习算法解读及基于飞桨的代码实现
  11. 为赢过老婆打造自动瞄准弓,闭眼也能百发百中,零件电路算法全自制
  12. 即时通讯软件:(c++实现)
  13. 直方图中bin的说明
  14. 在桌面右键菜单添加【切换电源计划-卓越性能】选项
  15. 思科配置系统日志服务器配置,思科交换机路由器配置日志服务器脚本
  16. web系统多语言切换
  17. L1-040. 最佳情侣身高差 java
  18. Java微信开发以及对各种云的评价
  19. 微信开通过滤 快速微信开通过滤软件
  20. python把变量加入列表,Python 变量列表 初学者笔记

热门文章

  1. 【js课设】电子画板01
  2. 那是你的计算机怎么用英语表示,“I potato you”可不是“我土豆你”,那这个potato到底啥意思?...
  3. [JZOJ1901] 【2010集训队出题】光棱坦克
  4. Windows 10 更新遇到错误代码 0x80240034 的解决方法
  5. 数据管理解决方案 | 零售行业如何搭建全渠道大数据平台?
  6. 《C和指针》阅读笔记
  7. 判断一个点是否在给定的凸四边形内
  8. Frammer X for Mac(视频截图软件)
  9. win10 关闭微软 Egde 浏览器后台
  10. 11款最受欢迎的亚马逊卖家工具