简述:
1.文件上传,也称为upload,是指将本地图片、视频、音频等文件上传到服务器上,可以供其他用户浏览或下载的过程。
2.文件上传在应用开发时,运用广泛,例如:大众点评分享笔记时上传图片,发朋友圈等都使用了文件上传功能。
本地存储
简介
本地存储即使将想要上传的文件上传到本地文件加上,当你启动项目时,自己的window机就相当于一个服务器,本地磁盘就可以成为文件上传的储存地。
主要步骤
1.选择文件,进行图片上传,将图片文件上传到服务器存储起来,然后返回图片访问的URL
2.当点击保存时,除了页面的基本表单数据需要提交到服务端,图片访问的URL,也需要提交到服务端
注意: 在SpringBoot中,文件上传,默认单个文件允许最大大小为 1M,如果需要上传大文件,可以在application.properties进行如下配置:
#配置单个文件的最大上传大小
spring.servlet.multipart.max-file-size=10MB
#配置单个请求最大上传大小(一次请求可以上传多个文件)
spring.servlet.multipart.max-request-size=100MB
实现步骤
首先,我现在基于一个项目来做,当我前端点击上传图片的时候,前端就会发送请求/common/upload到服务器,然后,项目基于图片路径进行下载/common/download回显。
代码如下:
@RestController
@RequestMapping("/common")
@Slf4j
public class CommonController {
@Value("${reggie.path}")
private String basePath;
@PostMapping("/upload")
public R<String> upload(MultipartFile file) throws IOException {
log.info("上传文件{}",file.toString());
// 封装文件名称,防止名称重复
String originalFilename = file.getOriginalFilename();
String suffix = originalFilename.substring(originalFilename.indexOf('.'));
String fileName = UUID.randomUUID().toString();
// 判断是否存在basePath,如果不存在,先创建
File dir = new File(basePath);
if(!dir.exists()){
// 目录不存在的话,创建目录
dir.mkdirs();
}
file.transferTo(new File(basePath+fileName+suffix));
return R.success(fileName+suffix);
}
/**
* 文件下载
* @param name 需要下载的文件名
* @param response 响应前端,回显图片
*/
@GetMapping("/download")
public void download(String name, HttpServletResponse response) throws IOException {
//输入流读取目标文件
FileInputStream inputStream = new FileInputStream(basePath + name);
//输出流回显数据
ServletOutputStream outputStream = response.getOutputStream();
//设置响应类型
response.setContentType("image/jpeg");
int len = 0;
byte[] bytes = new byte[1024];
//以bytes大小读取文件
while ((len=inputStream.read(bytes)) != -1){
outputStream.write(bytes,0,len);
outputStream.flush();
}
outputStream.close();
inputStream.close();
}
上面就是实现本地存储的步骤,baseUrl就是存储路径,前端传送的图片,视频,文件等都是MultipartFile类型的,然后使用transferTo就可以进行上传了。
实现效果
缺点
1.不安全:磁盘如果损坏,所有的文件就会丢失
2.容量有限:如果存储大量的图片,磁盘空间有限(磁盘不可能无限制扩容)
3.因为磁盘权限问题,无法直接访问
阿里云oss
简介
由于为了解决本地存储的缺点,就是用了阿里云OSS存储器,将图片存储到一个自己公共的云端上,便于自己操纵自己的文件。
主要步骤
实现步骤
1.首先注册阿里云:
进入到https://www.aliyun.com/进行注册
控制器->搜索OSS->开通OSS服务
2.创建bucker
3.获取AccessKey(密钥)
点击我的头像->AccessKey管理->创建AccessKey;每次使用就可以通过手机验证进行查看key跟KeySecret。
基于SDK实现一个小Demo
基于SDK进行实现阿里云OSS云存储
package com.itheima.reggie.common;
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请按实际情况填写。
String endpoint = "https://oss-cn-beijing.aliyuncs.com";
// 从环境变量中获取访问凭证。运行本代码示例之前,请确保已设置环境变量OSS_ACCESS_KEY_ID和OSS_ACCESS_KEY_SECRET。
// EnvironmentVariableCredentialsProvider credentialsProvider = CredentialsProviderFactory.newEnvironmentVariableCredentialsProvider();
// 填写Bucket名称,例如examplebucket。
String bucketName = "换成自己的buckName名称";
// 填写Object完整路径,完整路径中不能包含Bucket名称,例如exampledir/exampleobject.txt。
String objectName = "上传文件后的名字";
// 填写本地文件的完整路径,例如D:\\localpath\\examplefile.txt。
// 如果未指定本地路径,则默认从示例程序所属项目对应本地路径中上传文件流。
String filePath = "上传文件的具体位置";
String accessKeyId = "换成自己的accessKeyId";
String accessKeySecret = "通过手机验证查看自己的accessKeySecret";
// 创建OSSClient实例。
OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId,accessKeySecret);
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();
}
}
}
}
我这里并没有基于EnvironmentVariableCredentialsProvider创建OSSClient实例。而是通过OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId,accessKeySecret)进行创建。
运行效果
这样就可以将自己本地的文件上传到阿里云上了,然后前端想进行回显,也不需要进行下载了,直接< img src=“url”> 即可。
封装成一个工具类进行使用
1.封装工具类AliOssUtil
@Data
@AllArgsConstructor
@Slf4j
public class AliOssUtil {
private String endpoint;
private String accessKeyId;
private String accessKeySecret;
private String bucketName;
/**
* 文件上传
*
* @param bytes
* @param objectName
* @return
*/
public String upload(byte[] bytes, String objectName) {
// 创建OSSClient实例。
OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);
try {
// 创建PutObject请求。
ossClient.putObject(bucketName, objectName, new ByteArrayInputStream(bytes));
} 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();
}
}
//文件访问路径规则 https://BucketName.Endpoint/ObjectName
StringBuilder stringBuilder = new StringBuilder("https://");
stringBuilder
.append(bucketName)
.append(".")
.append(endpoint)
.append("/")
.append(objectName);
log.info("文件上传到:{}", stringBuilder.toString());
return stringBuilder.toString();
}
}
2.使用AliOssProperties注入工具类属性
@Component
@ConfigurationProperties(prefix = "reggie.alioss")
@Data
public class AliOssProperties {
private String endpoint;
private String accessKeyId;
private String accessKeySecret;
private String bucketName;
}
3.在配置文件设置自己的属性值
4.更新之前的upload方法
@Autowired
private AliOssUtil aliOssUtil;
// 基于阿里OSS进行文件存储
@PostMapping("/upload")
public R<String> upload(MultipartFile file){
try {
// 封装存储名字
String originalFilename = file.getOriginalFilename();
String extension = originalFilename.substring(originalFilename.lastIndexOf("."));
String objectName = UUID.randomUUID().toString()+extension;
String filePath = aliOssUtil.upload(file.getBytes(), objectName);
return R.success(filePath);
} catch (IOException e) {
e.getStackTrace();
}
return R.error("未知错误");
}
5.效果展示
补充说明
通过上面步骤就实现了将文件上传到阿里云OSS对象存储上,这里上传成功后,每个文件都会有一个url地址,当你想下载的时候,直接进行url应用即可。