首先是shiro權限管理,要配置文件上傳攔截器
//upload文件上傳
filterRuleMap.put("/upload/**", “anon”);
@Configuration
public class ShiroConfig {
@Autowired
private RedisUtil redisUtil;
/**
* 先走 filter
*
* @param securityManager the security manager
* @return the shiro filter factory bean
*/
@Bean
public ShiroFilterFactoryBean factory(SecurityManager securityManager) {
ShiroFilterFactoryBean factoryBean = new ShiroFilterFactoryBean();
factoryBean.setSecurityManager(securityManager);
Map<String, Filter> filterMap = new HashMap<>();
//設置自定義的JWT過濾器
filterMap.put("jwt", new JWTFilter(redisUtil));
factoryBean.setFilters(filterMap);
Map<String, String> filterRuleMap = new HashMap<>(2);
filterRuleMap.put("/auth/**", "anon");
filterRuleMap.put("/auth/authorization", "anon");
filterRuleMap.put("/auth/authentication", "anon");
filterRuleMap.put("/goods/**", "anon");
//upload文件上傳
filterRuleMap.put("/upload/**", "anon");
// filterRuleMap.put("/**", "jwt");
filterRuleMap.put("/**", "anon");
factoryBean.setFilterChainDefinitionMap(filterRuleMap);
return factoryBean;
}
/**
* 注入 securityManager
*
* @return the security manager
*/
@Bean
public SecurityManager securityManager() {
DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
// 設置自定義 realm.
securityManager.setRealm(customRealm());
/*
* 關閉shiro自帶的session,詳情見文檔
* http://shiro.apache.org/session-management.html#SessionManagement-StatelessApplications%28Sessionless%29
*/
DefaultSubjectDAO subjectDAO = new DefaultSubjectDAO();
DefaultSessionStorageEvaluator defaultSessionStorageEvaluator = new DefaultSessionStorageEvaluator();
defaultSessionStorageEvaluator.setSessionStorageEnabled(false);
subjectDAO.setSessionStorageEvaluator(defaultSessionStorageEvaluator);
securityManager.setSubjectDAO(subjectDAO);
return securityManager;
}
@Bean
public CustomRealm customRealm() {
CustomRealm customRealm = new CustomRealm();
return customRealm;
}
/**
* 開啓shiro aop註解支持. 使用代理方式; 所以需要開啓代碼支持;
*
* @param securityManager 安全管理器
* @return 授權Advisor
*/
@Bean
public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(SecurityManager securityManager) {
AuthorizationAttributeSourceAdvisor advisor = new AuthorizationAttributeSourceAdvisor();
advisor.setSecurityManager(securityManager);
return advisor;
}
}
緊接着就是文件管理配置類,將訪問的url和文件路徑寫上去
registry.addResourceHandler("/driver/**").addResourceLocations(“file:”+filePath+"/upload/driver/");
@Configuration
public class FileConfig extends WebMvcConfigurerAdapter {
@Value("${filePath}")
private String filePath;
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
//上傳的圖片在D盤下的OTA目錄下,訪問路徑如:http://localhost:8081/OTA/d3cf0281-bb7f-40e0-ab77-406db95ccf2c.jpg
//其中OTA表示訪問的前綴。"file:D:/OTA/"是文件真實的存儲路徑
registry.addResourceHandler("/goods/**").addResourceLocations("file:"+filePath+"/image/goods/");
registry.addResourceHandler("/driver/**").addResourceLocations("file:"+filePath+"/upload/driver/");
registry.addResourceHandler("/commodityInspection/**").addResourceLocations("file:"+filePath+"/upload/commodityInspection/");
registry.addResourceHandler("/fhhQualification/**").addResourceLocations("file:"+filePath+"/upload/fhhQualification/");
registry.addResourceHandler("/certificate/**").addResourceLocations("file:"+filePath+"/upload/certificate/");
}
}
接下來便是代碼實現了,先通過文件上傳通用類獲取url,保存到數據庫中
@RestController
@RequestMapping("/FileLibrary")
@Api(tags = "文件管理")
public class FileLibraryController extends BaseController {
@Autowired
private IFileLibraryService fileLibraryService;
@PostMapping("/uploadFile")
@ApiOperation("司機證件上傳")
public Object uploadFile(Integer id, MultipartFile file) {
//文件存儲位置
String filePathKeyword="/upload/driver";
//文件訪問地址
String urlPathKeyword="driver";
//前綴
String filePrefix="driver";
//文件名
String filename = file.getOriginalFilename();
FileLibrary fileLibrary = new FileLibrary();
fileLibrary.setFileId(id);
fileLibrary.setType(1);
fileLibrary.setFormerName(filename);
String url = fileLibraryService.uploadFile(file, filePrefix, filePathKeyword, urlPathKeyword);
fileLibrary.setUrl(url);
return fileLibraryService.save(fileLibrary)?ResultJson.ok():ResultJson.failure(ResultCode.BAD_REQUEST);
}
@PostMapping("/editDriver")
@ApiOperation("司機證件修改")
public Object editDriver(FileLibrary fileLibrary, MultipartFile file) {
//文件存儲位置
String filePathKeyword="/upload/driver";
//文件訪問地址
String urlPathKeyword="driver";
//前綴
String filePrefix="driver";
//文件名
String filename = file.getOriginalFilename();
FileLibrary one = fileLibraryService.getOne(new QueryWrapper<FileLibrary>().eq("file_id", fileLibrary.getFileId()).eq("type", 1));
if (one==null) {
return ResultJson.failure(ResultCode.NOT_EXIST);
} else {
fileLibraryService.deleteFile(one.getUrl(), filePathKeyword);
}
String url = fileLibraryService.uploadFile(file, filePrefix, filePathKeyword, urlPathKeyword);
fileLibrary.setFormerName(filename);
fileLibrary.setUrl(url);
return fileLibraryService.updateById(fileLibrary)? ResultJson.ok():ResultJson.failure(ResultCode.BAD_REQUEST);
}
}
Service接口
public interface IFileLibraryService extends IService<FileLibrary> {
/**
* 刪除文件
* @param file
* @param filePrefix
* @param filePathKeyword 前後不要加下劃線
* @param urlPathKeyword 前後不要加下劃線
* @return
* @throws Exception
*/
public String uploadFile(MultipartFile file, String filePrefix, String filePathKeyword, String urlPathKeyword);
/**
* 刪除文件
* @param fileUrl
* @param filePathKeyword
* @return
*/
public String deleteFile(String fileUrl, String filePathKeyword);
}
文件上傳通用實現類,用於獲取文件的url和刪除文件
@Service
public class FileLibraryServiceImpl extends ServiceImpl<FileLibraryMapper, FileLibrary> implements IFileLibraryService {
@Value("${filePath}")
private String filePath;
/**
* 上傳文件
* 例 文件夾地址 /filePath/filePathKeyword/filePrefix_123.jpg
* url訪問路徑 /filePath/urlPathKeyword/filePrefix_123.jpg
* @param file
* @param filePrefix 文件名前綴
* @param filePathKeyword 文件夾名(可多個文件夾) 前後不要加下劃線
* @param urlPathKeyword url指向名 前後不要加下劃線
* @return
* @throws Exception
*/
@Override
public String uploadFile(MultipartFile file, String filePrefix, String filePathKeyword, String urlPathKeyword){
String suffix = file.getOriginalFilename().substring(file.getOriginalFilename().lastIndexOf(".")).toLowerCase();
if (file.getSize() > 2000000) {
return "文件過大";
}
//文件保存路徑
File files = new File(filePath +File.separator+ filePathKeyword + File.separator);
if (!files.exists()) {
files.mkdirs();
}
//文件名: 前綴 + 日期時間 + 隨機數 + 文件類型
String targetName = filePrefix + "_" + System.currentTimeMillis() + (int) ((Math.random() * 9 + 1) * 100000) + suffix;
String path = files + File.separator + targetName;
try {
file.transferTo(new File(path));
} catch (IOException e) {
e.printStackTrace();
return null;
}
String url = (File.separator + urlPathKeyword+ File.separator + targetName);
return url;
}
/**
* 刪除文件
* @param fileUrl
* @param filePathKeyword
* @return
*/
@Override
public String deleteFile(String fileUrl, String filePathKeyword){
if(fileUrl!=null&&!"".equals(fileUrl)){
String[] split = fileUrl.split("\\/");
try {
File f = new File(filePath+File.separator+filePathKeyword+File.separator+split[split.length-1]);
if(f.exists()){
f.delete();
return "刪除成功";
}
}catch (Exception e){
e.printStackTrace();
return "刪除失敗";
}
}
return "刪除失敗";
}
}
Mapper
public interface FileLibraryMapper extends BaseMapper<FileLibrary> {
}
文件上傳的實體,與數據庫中相應的表字段對應
@Data
public class FileLibrary implements Serializable {
private static final long serialVersionUID = 1L;
/**
* id
*/
private Integer id;
/**
* 文件id
*/
private Integer fileId;
/**
* 文件類型 1代表司機的證件
*/
private Integer type;
/**
* 文件原名
*/
private String formerName;
/**
* 文件地址
*/
private String url;
/**
* 數據創建時間
*/
private Date createTime;
/**
* 創建人
*/
private String createBy;
/**
* 更改時間
*/
private Date updateTime;
/**
* 更改人
*/
private String updateBy;
/**
* 備註
*/
private String remark;
public FileLibrary() {
}
}