1.标题
- 实际开发中经常会用到文件的上传和下载功能,如果是上传到本地有很多种方法,但是如果上传到Fdfs资源服务器就需要借助其他的工具类,现在比较火的就是开源工具com.github.tobato.fastdfs
2. 工具和实现
1.Maven中引入Jar包
<dependency>
<groupId>com.github.tobato</groupId>
<artifactId>fastdfs-client</artifactId>
<version>1.26.2</version>
</dependency>
2. 文件上传和下载实现类
@Slf4j
@Service
@Transactional(rollbackFor = Exception.class)
@Import(FdfsClientConfig.class)
@EnableMBeanExport(registration = RegistrationPolicy.IGNORE_EXISTING)
public class AttachmentServiceImpl implements AttachmentService {
@Autowired
private AttachmentRepository attachmentRepository;
// 注入工具类
@Autowired
private FastFileStorageClient fastFileStorageClient;
/**
* 上传文件
*/
@Override
public AttachmentVo uploader(MultipartFile file, String contentId) {
//如果判断所属内容id为空,则生成一个并返回
if (StringUtils.isBlank(contentId)) {
contentId = UUIDUtils.newUUID().toString();
}
try {
// 获取文件名称
String originalFilename = file.getOriginalFilename();
Set<MataData> mataData = new HashSet<>(2);
// 设置文件编码格式
String fileName = URLEncoder.encode(originalFilename, "UTF-8");
fileName = new String(fileName.getBytes("ISO-8859-1"), "UTF-8");
// 将文件放入
mataData.add(new MataData("fileName", fileName));
log.debug("upload file with origin filename: {}", originalFilename);
// 调用方法传入资源服务器中
StorePath storePath = fastFileStorageClient.uploadFile(file.getInputStream(), file.getSize(),
FilenameUtils.getExtension(file.getOriginalFilename()), mataData);
// TODO 保存相关对象到数据库 并返回
return null;
} catch (IOException e) {
log.error("file upload failed with message: {}", e.getMessage());
throw new StandardException("附件上传失败!");
}
}
/**
* 查找文件
*/
@Override
public List<AttachmentQueryVo> findByContentId(QueryAttachmentAction request) {
String contentId = request.getContentId();
List<AttachmentEntity> byContentId = attachmentRepository.findByContentId(contentId, DeletedType.NON);
return BeanUtils.copyCollection(byContentId, AttachmentQueryVo.class);
}
/**
* 删除文件
*/
@Override
@Transactional(rollbackFor = RuntimeException.class)
public Boolean deleteFile(DeleteAttachmentAction deleteAttachmentAction) {
String id = deleteAttachmentAction.getId();
Optional<AttachmentEntity> optional = attachmentRepository.findById(id);
if (!optional.isPresent()) {
throw new StandardException("附件未找到!");
}
AttachmentEntity attachmentEntity = optional.get();
attachmentEntity.setDeleted(DeletedType.DEL);
attachmentRepository.save(attachmentEntity);
return true;
}
/**
* 下载文件
*/
@Override
public void fileDownload(String id, String fullPath, HttpServletResponse response) {
String group = "";
String path = "";
if (StringUtils.isBlank(id) && StringUtils.isBlank(fullPath)) {
Assert.assertNotEmpty(id, "文件id或者url不能同时为空!");
}
// 如果ID为空 获取下载地址
if (StringUtils.isNotBlank(id)) {
AttachmentEntity entity = attachmentRepository.getOne(id);
Assert.assertNotNull(entity, "附件未找到!");
StorePath storePath = StorePath.praseFromUrl(entity.getDownloadUrl());
group = storePath.getGroup();
path = storePath.getPath();
}
// 如果ID和fullPath 都不为空 获取预览地址
if (StringUtils.isBlank(id) && StringUtils.isNotBlank(fullPath)) {
group = fullPath.substring(0, fullPath.indexOf("/"));
path = fullPath.substring(fullPath.indexOf("/") + 1);
}
try {
// 根据地址获取资源服务器中的文件名称
Set<MataData> set = fastFileStorageClient.getMetadata(group, path);
String fileOriginName = set.stream().filter(mataData -> "fileName".equals(mataData.getName()))
.findFirst().orElse(new MataData("fileName", "文件名已丢失")).getValue();
log.debug("download file with origin filename: {}", fileOriginName);
response.setContentType("application/octet-stream");
//设置导出编码格式
response.setHeader("Content-disposition", "attachment;filename=" + fileOriginName + ";" + "filename*=utf-8''" + fileOriginName);
OutputStream out = response.getOutputStream();
String downloadResult = fastFileStorageClient.downloadFile(group, path, in -> {
try {
IOUtils.copy(in, out);
} catch (IOException e) {
log.error("download file failed: {}", e.getMessage());
return "failed!";
} finally {
IOUtils.closeQuietly(in);
IOUtils.closeQuietly(out);
}
return "success!";
});
} catch (IOException e) {
e.printStackTrace();
}
}
3. 配置文件中配置
fdfs:
so-timeout: 10000
connect-timeout: 30000
tracker-list: localhost:22122
pool:
max-total: 3000
max-wait-millis: 30000