前端代码
<form action="/upload" method="post" enctype="multipart/form-data">姓名: <input type="text" name="username"><br>年龄: <input type="text" name="age"><br>头像: <input type="file" name="image"><br><input type="submit" value="提交">
</form>
上传文件的原始form表单,要求表单必须具备以下三点(上传文件页面三要素):
-
表单必须有file域,用于选择要上传的文件
<input type="file" name="image"/>
-
表单提交方式必须为POST
通常上传的文件会比较大,所以需要使用 POST 提交方式
-
表单的编码类型enctype必须要设置为:multipart/form-data
普通默认的编码格式是不适合传输大型的二进制数据的,所以在文件上传时,表单的编码格式必须设置为multipart/form-data
本地存储
Spring中提供了一个API:MultipartFile,使用这个API就可以来接收到上传的文件
代码实现:
- 在服务器本地磁盘上创建images目录,用来存储上传的文件(例:E盘创建images目录)
- 使用MultipartFile类提供的API方法,把临时文件转存到本地磁盘目录下
MultipartFile 常见方法:
- String getOriginalFilename(); //获取原始文件名
- void transferTo(File dest); //将接收的文件转存到磁盘文件中
- long getSize(); //获取文件的大小,单位:字节
- byte[] getBytes(); //获取文件内容的字节数组
- InputStream getInputStream(); //获取接收到的文件内容的输入流
@Slf4j
@RestController
public class UploadController {@PostMapping("/upload")public Result upload(String username, Integer age, MultipartFile image) throws IOException {log.info("文件上传:{},{},{}",username,age,image);//获取原始文件名String originalFilename = image.getOriginalFilename();/构建新的文件名String extname = originalFilename.substring(originalFilename.lastIndexOf("."));//文件扩展名String newFileName = UUID.randomUUID().toString()+extname;//随机名+文件扩展名//将文件存储在服务器的磁盘目录image.transferTo(new File("E:/images/"+newFileName));return Result.success();}}
在SpringBoot中,文件上传时默认单个文件最大大小为1M。如果需要上传大文件,可以在application.properties进行如下配置:
#配置单个文件最大上传大小
spring.servlet.multipart.max-file-size=10MB#配置单个请求最大上传大小(一次请求可以上传多个文件)
spring.servlet.multipart.max-request-size=100MB
阿里云OSS
登录阿里云 => 开通OSS服务之后,进入到阿里云对象存储的控制台 => 点击左侧的 "Bucket列表",创建一个Bucket
官方提供的SDK
import com.aliyun.oss.ClientException;
import com.aliyun.oss.OSS;
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 AliOssTest {public static void main(String[] args) throws Exception {// Endpoint以华东1(杭州)为例,其它Region请按实际情况填写。String endpoint = "oss-cn-shanghai.aliyuncs.com";// 阿里云账号AccessKey拥有所有API的访问权限,风险很高。强烈建议您创建并使用RAM用户进行API访问或日常运维,请登录RAM控制台创建RAM用户。String accessKeyId = "LTAI5t9MZK8iq5T2Av5GLDxX";String accessKeySecret = "C0IrHzKZGKqU8S7YQcevcotD3Zd5Tc";// 填写Bucket名称,例如examplebucket。String bucketName = "web-framework01";// 填写Object完整路径,完整路径中不能包含Bucket名称,例如exampledir/exampleobject.txt。String objectName = "1.jpg";// 填写本地文件的完整路径,例如D:\\localpath\\examplefile.txt。// 如果未指定本地路径,则默认从示例程序所属项目对应本地路径中上传文件流。String filePath= "C:\\Users\\Administrator\\Pictures\\1.jpg";// 创建OSSClient实例。OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);try {InputStream inputStream = new FileInputStream(filePath);// 创建PutObjectRequest对象。PutObjectRequest putObjectRequest = new PutObjectRequest(bucketName, objectName, inputStream);// 设置该属性可以返回response。如果不设置,则返回的response为空。putObjectRequest.setProcess("true");// 创建PutObject请求。PutObjectResult result = ossClient.putObject(putObjectRequest);// 如果上传成功,则返回200。System.out.println(result.getResponse().getStatusCode());} 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();}}}
}
在以上代码中,需要替换的内容为:
- accessKeyId:阿里云账号AccessKey
- accessKeySecret:阿里云账号AccessKey对应的秘钥
- bucketName:Bucket名称
- objectName:对象名称,在Bucket中存储的对象的名称
- filePath:文件路径
AccessKey :
运行以上程序后,会把本地的文件上传到阿里云OSS服务器上。
集成
阿里云oss对象存储服务的准备工作以及入门程序我们都已经完成了,接下来我们就需要在案例当中集成oss对象存储服务,来存储和管理案例中上传的图片。
在新增员工的时候,上传员工的图像,而之所以需要上传员工的图像,是因为将来我们需要在系统页面当中访问并展示员工的图像。而要想完成这个操作,需要做两件事:
- 需要上传员工的图像,并把图像保存起来(存储到阿里云OSS)
- 访问员工图像(通过图像在阿里云OSS的存储地址访问图像)
- OSS中的每一个文件都会分配一个访问的url,通过这个url就可以访问到存储在阿里云上的图片。所以需要把url返回给前端,这样前端就可以通过url获取到图像。
引入阿里云OSS上传文件工具类(由官方的示例代码改造而来)
import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClientBuilder;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;import java.io.IOException;
import java.io.InputStream;
import java.util.UUID;@Component
public class AliOSSUtils {private String endpoint = "https://oss-cn-shanghai.aliyuncs.com";private String accessKeyId = "LTAI5t9MZK8iq5T2Av5GLDxX";private String accessKeySecret = "C0IrHzKZGKqU8S7YQcevcotD3Zd5Tc";private String bucketName = "web-framework01";/*** 实现上传图片到OSS*/public String upload(MultipartFile multipartFile) throws IOException {// 获取上传的文件的输入流InputStream inputStream = multipartFile.getInputStream();// 避免文件覆盖String originalFilename = multipartFile.getOriginalFilename();String fileName = UUID.randomUUID().toString() + originalFilename.substring(originalFilename.lastIndexOf("."));//上传文件到 OSSOSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);ossClient.putObject(bucketName, fileName, inputStream);//文件访问路径String url = endpoint.split("//")[0] + "//" + bucketName + "." + endpoint.split("//")[1] + "/" + fileName;// 关闭ossClientossClient.shutdown();return url;// 把上传到oss的路径返回}
}
修改UploadController代码:
import com.itheima.pojo.Result;
import com.itheima.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.RestController;
import org.springframework.web.multipart.MultipartFile;
import java.io.IOException;@Slf4j
@RestController
public class UploadController {@Autowiredprivate AliOSSUtils aliOSSUtils;@PostMapping("/upload")public Result upload(MultipartFile image) throws IOException {//调用阿里云OSS工具类,将上传上来的文件存入阿里云String url = aliOSSUtils.upload(image);//将图片上传完成后的url返回,用于浏览器回显展示return Result.success(url);}}