1、简介
- 文件上传,指的是将本地的图片、视频等文件上传到服务器,供其他用户浏览或下载的过程。
- 文件上传在项目中应用非常广泛,外卖日常使用的微博朋友圈等都利用了文件上传功能。
1)文件上传需要前端的三个要素:
- 需要一个 form 表单,令表单的提交方式为 post 来处理较大文件的传输。
- 使用 enctype 来指定表单的编码格式为 multipart/form-data,普通默认的格式不适用于传输大文件数据,如果表单的编码格式设置为默认的,则传输上来的仅仅是文件的文件名。
- 定义一个表单项为 file。
2)服务端来接收文件
服务端通过 MultipartFile 类型来接收传输过来的文件
2、本地存储
上面的情况下,我们接收下来的文件是在本地存储为临时文件,但是当程序运行结束后,本地的文件是不会存储下来的,那我们应该将这些文件存储下来呢?下面我们来学习本地存储的方法。
1)定义
在服务端,接收到上传来的文件之后,将文件存储在本地服务器的磁盘中。
2)实现
transferTo
方法是Spring框架中Resource
接口的一个方法,它用于将资源(Resource)的内容复制到一个输出流(OutputStream
)中。这个方法通常用于将资源的内容传输到文件、HTTP响应或其他输出目标中。
利用上述的方法可以直接将传入的文件放入一个文件之中
通过 new 一个 File 对象的方法来直接将传递过来的文件放入这个 new 的 File 对象中,但同时发现了一个问题,当我们直接指定文件的名称的时候,会导致存储的重名问题,这时候我们可以通过得到传输来的文件名称,并且通过这个名称来为我们本地的文件命名。
- 通过 getOriginalFilename 来获取文件的初始名称
String name = image.getOriginalFilename();
image.tranferTo(new File("E:\\images\\" + name));
虽然这个方法解决了一部分上传的同名问题,但是当有多个用户来同时传输文件的时候,还是有可能出现重名的情况,那应该如何获取到一个不会重复的数据呢?
String name = image.getOriginalFilename();
// 例如 hello.world.jpg 我们想要拿到文件的拓展名 jpg 就需要找到最后一个 . 出现的位置
int index = name.lastIndexOf(".");
String extname = name.substing(index);
String newFileName = UUID.randomUUID() + extname;
image.tranferTo(new File("E:\\images\\" + new Filename));
3)实现大文件的上传
在 springboot 中默认单个文件允许的最大大小为 1M,超过的时候就会报错,如果我们需要上传大文件就需要进行配置。
// 配置单个文件最大上传大小
spring.servlet.multipart.max.file-size = 10MB
// 配置单个请求中文件的上传大小
spring.servlet.multipart.max-request-size = 100MB
4)常见方法总结
3、阿里云 OSS
阿里云是阿里巴巴旗下的全球领先的云计算公式,也是国内最大的云服务提供商。
阿里云对象存储服务,是一款海量、安全、低成本、高可靠的云存储服务。使用 OSS,可以通过网络随时存储和调用各种文件。
1)使用第三方服务的通用思路
SDK:软件开发工具包,包括辅助软件开发的依赖(jar 包)、代码实例,都可以叫做 SDK。
2)阿里云 OSS - 使用步骤
Bucket:存储空间是用户用于存储对象的容器,所有的对象都必须隶属于某个存储空间。
官方文档(SDK)地址:如何安装OSS Java SDK_对象存储 OSS-阿里云帮助中心 (aliyun.com)
官方示例代码:
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-hangzhou.aliyuncs.com";
// 从环境变量中获取访问凭证。运行本代码示例之前,请确保已设置环境变量OSS_ACCESS_KEY_ID和OSS_ACCESS_KEY_SECRET。
EnvironmentVariableCredentialsProvider credentialsProvider = CredentialsProviderFactory.newEnvironmentVariableCredentialsProvider();
// 填写Bucket名称,例如examplebucket。
String bucketName = "examplebucket";
// 填写Object完整路径,完整路径中不能包含Bucket名称,例如exampledir/exampleobject.txt。
String objectName = "exampledir/exampleobject.txt";
// 填写本地文件的完整路径,例如D:\\localpath\\examplefile.txt。
// 如果未指定本地路径,则默认从示例程序所属项目对应本地路径中上传文件流。
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();
}
}
}
}