目录
[案例集成OSS (文件上传接口的实现)](#案例集成OSS (文件上传接口的实现))
前端页面三要素(file表单项、post方法、multipart/form-data)
简介
- 文件上传,是指将本地图片、视频、音频等文件上传至服务器,供其他用户浏览或者下载的过程
- 文件上传在项目中应用非常广泛,我们经常发微博、发朋友圈都要用到文件上传功能。
文件上传前端页面三要素
表单项file
表单提交方式
表单的编码格式
上述页面运行结果为:
服务端接收文件
控制类代码如下:
java
package com.example.tlias.controller;
import com.example.tlias.pojo.Result;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
@RestController
@Slf4j
public class UpLoadController {
@PostMapping("upload")
public Result upload(String username, Integer age, MultipartFile image) {
log.info("文件上传,name:{},age:{},image:{}", username, age, image);
return Result.success();
}
}
调试运行SpringBoot项目,在浏览器中访问html前端页面,设置程序断点,如果不设置断点,程序运行完成之后,接收的临时文件会自动删除。具体示意如下:
然后在浏览器中访问前端页面
点击提交后, 程序终端显示如下:
显示接收到前端的数据以及数据临时存放的位置
小结
- 前端页面三要素
- 表单项 type="file"
- 表单提交方式 post
- 表单的enctype属性 multipart/form-data
- 服务端接收wenjian
- MultipartFile
本地储存
实现
-
在服务端,接收到上传上来的文件之后,将文件存储在本地服务器磁盘中
-
具体控制类代码如下
*javapackage com.example.tlias.controller; import com.example.tlias.pojo.Result; import lombok.extern.slf4j.Slf4j; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.multipart.MultipartFile; import java.io.File; import java.io.IOException; @RestController @Slf4j public class UpLoadController { @PostMapping("upload") public Result upload(String username, Integer age, MultipartFile image) throws IOException { log.info("文件上传,name:{},age:{},image:{}", username, age, image); // todo 获取原始文件名 String name = image.getOriginalFilename(); // todo 将文件存储在服务器指定的磁盘目录中 image.transferTo(new File("D:\\downloadFile\\" + name)); return Result.success(); } }
使用psotman进行测试
具体请求路径以及请求参数如下
在对应的文件目录中显示如下:
成功将前端传递的文件存储到本地服务器的磁盘中
代码优化
-
存在的问题:当前端传递的文件名称相同时,就会出现文件覆盖的问题
-
问题的解决:为每一个接收到的文件重新设置一个新的名字即可,新的名字由UUID以及该文件的后缀名组成,UUID使用java自带的aip进行生成,后缀名通过截取文件原名称所得
-
具体代码如下:
*javapackage com.example.tlias.controller; import com.example.tlias.pojo.Result; import lombok.extern.slf4j.Slf4j; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.multipart.MultipartFile; import java.io.File; import java.io.IOException; import java.util.UUID; @RestController @Slf4j public class UpLoadController { @PostMapping("upload") public Result upload(String username, Integer age, MultipartFile image) throws IOException { log.info("文件上传,name:{},age:{},image:{}", username, age, image); // todo 获取原始文件名,但是不同文件的原始文件名可能相同 String name = image.getOriginalFilename(); // todo 构造唯一文件名--uuid(通用唯一识别码) // 获取文件后缀名 int index = name.lastIndexOf(".");//获取最后的.的索引位置 String extname = name.substring(index);//进行截取 String newName = UUID.randomUUID().toString() + extname;//创建唯一文件名 log.info("获取到的新的文件名为:{}", newName); // todo 将文件存储在服务器指定的磁盘目录中 image.transferTo(new File("D:\\downloadFile\\" + newName)); return Result.success(); } }
使用postman重新发送相同的请求,运行结果如下:
问题成功解决
在SpringBoot中,文件上传,默认单个文件允许最大大小为1M,如果需要上传大文件,可以进行如下配置
小结
- String getOriginalFilename() -->获取原始文件名
- void transferTo(File dest)-->将接受文件转存到磁盘文件中
- long getSize() -->获取文件大小,单位字节(byte) 1KB=1024字节
- byte[ ] getBytes() --> 获取文件内容的字节数组
- InputStream getInputStream() -->获取接收到的文件内容的输入流
阿里云OSS
阿里云
- 阿里云是阿里巴巴集团旗下全球领先的云计算公司,也是国内最大的云服务提供商
阿里云OSS
- 阿里云对象存储OSS(Object Storage Service ),是一款海量、安全、低成本、高可靠的云存储服务。使用OSS,可以通过网路随时存储和调用包括文本、图片、音频和视频等在内的各种文件。
使用第三方服务--通用思路
准备工作
参照官方SDK代码,编写入门程序
SDK是软件开发工具包(Software Development Kit)的缩写,它是一组用于开发特定软件应用或平台的工具、库和文档的集合。SDK提供了开发者所需的工具和资源,以便他们能够更轻松地创建、测试和部署软件应用。SDK通常包含编译器、调试器、API文档、示例代码和其他开发工具,以及与特定平台或操作系统交互的库和组件。开发者可以使用SDK来构建应用程序、插件、扩展或其他软件组件,以便与特定的软件、硬件或服务进行集成。
集成使用
阿里云OSS-使用步骤
阿里云OSS使用步骤
注册阿里云---充值(选做)---开通对象存储服务(OSS)---创建bucket---获取AccessKey(密钥)---参照官方SDK编写入门使用----案例集成OSS
- Bucket:存储空间是用户用于存储对象(object,就是文件)的容器,所有对象都必须隶属于某个存储空间。
具体使用步骤参照一下文件:
【腾讯文档】SpringBoot案例所需文档
https://docs.qq.com/doc/DUkRiTWVaUmFVck9N
参照SDK编写入门程序
根据阿里云官方提供的文档进行操作即可
-
首先安装Java JDK
-
然后进行需要进行的OSS操作
复制对应的代码即可,根据自己的信息修改其中的具体代码
我要使用文件上传的功能,具体代码如下:
java
package com.example.tlias;
import com.aliyun.oss.ClientException;
import com.aliyun.oss.OSS;
import com.aliyun.oss.common.auth.*;
import com.aliyun.oss.OSSClientBuilder;
import com.aliyun.oss.OSSException;
import com.aliyun.oss.model.PutObjectRequest;
import com.aliyun.oss.model.PutObjectResult;
import java.io.FileInputStream;
import java.io.InputStream;
public class Demo {
public static void main(String[] args) throws Exception {
// Endpoint以华东1(杭州)为例,其它Region请按实际情况填写。
// todo 指定OSS服务地址
String endpoint = "https://oss-cn-hangzhou.aliyuncs.com";
// todo 设置访问凭证
// 从环境变量中获取访问凭证。运行本代码示例之前,请确保已设置环境变量OSS_ACCESS_KEY_ID和OSS_ACCESS_KEY_SECRET。
EnvironmentVariableCredentialsProvider credentialsProvider = CredentialsProviderFactory.newEnvironmentVariableCredentialsProvider();
// 填写Bucket名称,例如examplebucket。
// todo 指定文件所存储的bucket名字(bucketName),以及文件的名称(objectName)
String bucketName = "examplebucket";
// 填写Object完整路径,完整路径中不能包含Bucket名称,例如exampledir/exampleobject.txt。
String objectName = "exampledir/exampleobject.txt";
// 填写本地文件的完整路径,例如D:\\localpath\\examplefile.txt。
// 如果未指定本地路径,则默认从示例程序所属项目对应本地路径中上传文件流。
// todo 指定本地要上传的文件
String filePath = "D:\\localpath\\examplefile.txt";
// 创建OSSClient实例。
OSS ossClient = new OSSClientBuilder().build(endpoint, credentialsProvider);
try {
InputStream inputStream = new FileInputStream(filePath);
// 创建PutObjectRequest对象。
PutObjectRequest putObjectRequest = new PutObjectRequest(bucketName, objectName, inputStream);
// 创建PutObject请求。
PutObjectResult result = ossClient.putObject(putObjectRequest);
} catch (OSSException oe) {
System.out.println("Caught an OSSException, which means your request made it to OSS, "
+ "but was rejected with an error response for some reason.");
System.out.println("Error Message:" + oe.getErrorMessage());
System.out.println("Error Code:" + oe.getErrorCode());
System.out.println("Request ID:" + oe.getRequestId());
System.out.println("Host ID:" + oe.getHostId());
} catch (ClientException ce) {
System.out.println("Caught an ClientException, which means the client encountered "
+ "a serious internal problem while trying to communicate with OSS, "
+ "such as not being able to access the network.");
System.out.println("Error Message:" + ce.getMessage());
} finally {
if (ossClient != null) {
ossClient.shutdown();
}
}
}
}
修改完具体的参数之后,允许一下该java程序,允许结果如下:
运行成功
并且会为每一个文件设置一个访问的url地址
案例集成OSS (文件上传接口的实现)
在员工案例中的对于新增员工接口功能的实现中,还没有实现对于员工头像信息的上传,头像上传功能的实现,参照接口文档中的文件上传接口,接口文档的具体链接如下:
https://hkm-web.oss-cn-beijing.aliyuncs.com/%E6%8E%A5%E5%8F%A3%E6%96%87%E6%A1%A3
引入阿里云OSS工具类
java
package com.example.tlias.utils;
import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClientBuilder;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import java.io.*;
import java.util.UUID;
/**
* 阿里云 OSS 工具类
*/
@Component
public class AliOSSUtils {
// todo 指定OSS服务地址
private String endpoint = "你自己的";
// todo 设置密钥账号和密码
private String accessKeyId = "你自己的";
private String accessKeySecret = "你自己的";
// todo 设置文件存储buket
private String bucketName = "你自己的";
/**
* 实现上传图片到OSS
*/
public String upload(MultipartFile file) throws IOException {
// 获取上传的文件的输入流
InputStream inputStream = file.getInputStream();
// 避免文件覆盖
String originalFilename = file.getOriginalFilename();
String fileName = UUID.randomUUID().toString() + originalFilename.substring(originalFilename.lastIndexOf("."));
//上传文件到 OSS
OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);
ossClient.putObject(bucketName, fileName, inputStream);
//文件访问路径
String url = endpoint.split("//")[0] + "//" + bucketName + "." + endpoint.split("//")[1] + "/" + fileName;
// 关闭ossClient
ossClient.shutdown();
return url;// 把上传到oss的路径返回
}
}
控制类
java
package com.example.tlias.controller;
import com.example.tlias.pojo.Result;
import com.example.tlias.utils.AliOSSUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import java.io.File;
import java.io.IOException;
import java.util.UUID;
@RestController
@Slf4j
public class UpLoadController {
// todo 文件存储到本地
// @PostMapping("/upload")
// public Result upload(String username, Integer age, MultipartFile image) throws IOException {
// log.info("文件上传,name:{},age:{},image:{}", username, age, image);
// // todo 获取原始文件名,但是不同文件的原始文件名可能相同
// String name = image.getOriginalFilename();
// // todo 构造唯一文件名--uuid(通用唯一识别码)
// // 获取文件后缀名
// int index = name.lastIndexOf(".");//获取最后的.的索引位置
// String extname = name.substring(index);//进行截取
// String newName = UUID.randomUUID().toString() + extname;//创建唯一文件名
// log.info("获取到的新的文件名为:{}", newName);
// // todo 将文件存储在服务器指定的磁盘目录中
// image.transferTo(new File("D:\\downloadFile\\" + newName));
// return Result.success();
// }
// todo 文件存储至阿里云OSS
@Autowired
private AliOSSUtils aliOSSUtils;
@PostMapping("/upload")
public Result upload(MultipartFile image) throws IOException {
log.info("文件上传至阿里云,文件名:{}", image.getOriginalFilename());
// 调用阿里云OSS工具进行文件上传
String url = aliOSSUtils.upload(image);
log.info("文件上传完成,文件url地址为:{}", url);
return Result.success(url);
}
}
测试
前后端联调
运行成功
小结
文件上传介绍
前端页面三要素(file表单项、post方法、multipart/form-data)
服务端接口接收文件(Multipart)
文件存储方式
- 本地存储(无法直接访问、磁盘空间受限、磁盘损坏)
- 云存储OSS