1. 图片上传
application.properties 配置上传文件路径
## 文件上传 ##
# 目标路径
pic.local-path=D:/PIC
# spring boot3 升级配置名
spring.web.resources.static-locations=classpath:/static/,file:${pic.local-path}
tip:
1. 如果访问的是本地路径,需要添加配置项::spring.web.resources.static-locations(springboot 3 升级过配置名,原本为 spring.resources.static-locations)
2. 访问静态资源不做拦截:AppConfig 类中 excludes 新增 "/*.jpg" 或者 "/*.png"
图片服务 PictureService 接口定义
package com.example.lotterysystem.service;
import org.springframework.web.multipart.MultipartFile;
public interface PictureService {
/**
* 保存图片
*
* @param multipartFile:上传文件的工具类
* 后面上传完图片后,需要将图片保存到项目中,因此需要一个索引来找到图片
* @return 返回值 String 就是索引:上传后的文件名(唯一)
*/
String savePicture(MultipartFile multipartFile);
}
接口实现 PictureServiceImpl
package com.example.lotterysystem.service.impl;
import com.example.lotterysystem.common.errorcode.ServiceErrorCodeConstants;
import com.example.lotterysystem.common.exception.ServiceException;
import com.example.lotterysystem.service.PictureService;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;
import java.io.File;
import java.io.IOException;
import java.util.UUID;
@Component
public class PictureServiceImpl implements PictureService {
@Value("${pic.local-path}")
private String localPath;
@Override
public String savePicture(MultipartFile multipartFile) {
// 创建目录
File dir = new File(localPath);
if (!dir.exists()) {
dir.mkdirs();
}
// 创建索引 aaa.jpg -> xxx.jpg
// 第一步:需要拿到当前文件的全名称,如:aaa.jpg
String filename = multipartFile.getOriginalFilename();
assert filename != null;
// 第二步:拿到当前文件的后缀名,如:.jpg
String suffix = filename.substring(filename.lastIndexOf("."));
// 第三步:生成索引,如:xxx
// 第四步:拼接 xxx.jpg(拼接为自己管控的文件名)
filename = UUID.randomUUID() + suffix;
// 图片保存
try {
// transferTo 方法将创建好的 multipartFile 保存到自定义的目录(localPath + "/" + filename)中
multipartFile.transferTo(new File(localPath + "/" + filename));
} catch (IOException e) {
throw new ServiceException(ServiceErrorCodeConstants.PIC_UPLOAD_ERROR);
}
return filename;
}
}
Postman 测试
在 D:\pic 目录下就能看到这个上传的图片了
2. 创建奖品
时序图
约定前后端交互接口
[请求] /prize/create POST
param: {"prizeName":"吹风机","description":"吹风机","price":100}
prizePic: Obj-C.jpg (FILE)[响应]
{
"code": 200,
"data": 17,
"msg": ""
}
Controller 层接口设计
package com.example.lotterysystem.controller;
import com.example.lotterysystem.common.pojo.CommonResult;
import com.example.lotterysystem.common.utils.JacksonUtil;
import com.example.lotterysystem.controller.param.CreatePrizeParam;
import com.example.lotterysystem.service.PictureService;
import com.example.lotterysystem.service.PrizeService;
import jakarta.validation.Valid;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestPart;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
@RestController
public class PrizeController {
private static final Logger logger = LoggerFactory.getLogger(PrizeController.class);
@Autowired
private PictureService pictureService;
@Autowired
private PrizeService prizeService;
@RequestMapping("/pic/upload")
public String uploadPic(MultipartFile file) {
return pictureService.savePicture(file);
}
/**
* 创建奖品
* @RequestPart:用于接受表单数据的 multipart/form-data
*
* @param param
* @param picFile
* @return
*/
@RequestMapping("/prize/create")
public CommonResult<Long> createPrizeParam(@Valid @RequestPart("param") CreatePrizeParam param,
@RequestPart("prizePic") MultipartFile picFile) {
logger.info("createPrizeParam CreatePrizeParam:{}", JacksonUtil.writeValueAsString(param));
return CommonResult.success(prizeService.createPrize(param, picFile));
}
}
CreatePrizeParam
package com.example.lotterysystem.controller.param;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
import lombok.Data;
import java.io.Serializable;
import java.math.BigDecimal;
@Data
public class CreatePrizeParam implements Serializable {
// 奖品名称
@NotBlank(message = "奖品名称不能为空!")
private String prizeName;
// 奖品描述
private String description;
// 奖品价格
@NotNull(message = "奖品价格不能为空!")
private BigDecimal price;
}
Service 层接口设计
package com.example.lotterysystem.service;
import com.example.lotterysystem.controller.param.CreatePrizeParam;
import org.springframework.web.multipart.MultipartFile;
public interface PrizeService {
/**
* 创建单个奖品
*
* @param param 奖品属性
* @param picFile 上传的奖品图片
* @return 奖品id
*/
Long createPrize(CreatePrizeParam param, MultipartFile picFile);
}
接口实现
package com.example.lotterysystem.service.impl;
import com.example.lotterysystem.common.errorcode.ServiceErrorCodeConstants;
import com.example.lotterysystem.common.exception.ServiceException;
import com.example.lotterysystem.service.PictureService;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;
import java.io.File;
import java.io.IOExcep