孤独没有什么不好。使孤独变得不好,是因为你害怕孤独。——《孤独六讲》
代码非常简单,像之前的实现:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73
| import cn.hutool.core.date.DateUtil; import cn.hutool.core.io.file.FileNameUtil; import cn.hutool.core.lang.UUID; import cn.hutool.core.text.StrPool; import cn.hutool.core.util.StrUtil; import cn.hutool.core.util.URLUtil; import cn.hutool.http.ContentType; import com.aliyun.oss.HttpMethod; import com.aliyun.oss.OSS; import com.aliyun.oss.model.DeleteObjectsRequest; import com.aliyun.oss.model.GeneratePresignedUrlRequest; import com.namaste.hsswobjectstorage.api.service.IOssService; import jakarta.annotation.Resource; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Service; import org.springframework.util.ObjectUtils;
import java.util.Date; import java.util.List;
import static java.util.stream.Collectors.*;
@Service public class AliOssServiceImpl implements IOssService {
@Resource private OSS ossClient;
@Override public String getPresignedUrlPut(String bucket, String fileName) { var expiration = new Date(new Date().getTime() + 3600 * 1000L); var objectName = DateUtil.date().toDateStr() + FileNameUtil.UNIX_SEPARATOR + UUID.fastUUID() + DateUtil.date().toTimestamp() + StrPool.DOT + FileNameUtil.extName(fileName); GeneratePresignedUrlRequest request = new GeneratePresignedUrlRequest(bucket, objectName, HttpMethod.PUT); request.setExpiration(expiration); request.setContentType(ContentType.OCTET_STREAM.getValue()); return ossClient.generatePresignedUrl(request).toString(); }
@Override public void deleteBatch(List<String> fileUrls) { if (ObjectUtils.isEmpty(fileUrls)) { return; } var bucketObjectsMap = fileUrls.stream() .collect(groupingBy( url -> url.substring(url.indexOf(StrPool.SLASH) + 2, url.indexOf(StrPool.DOT)), mapping(url -> StrUtil.removePrefix(URLUtil.getPath(url), StrPool.SLASH), toList()))); bucketObjectsMap.entrySet().stream() .map(entry -> { var req = new DeleteObjectsRequest(entry.getKey()); req.setKeys(entry.getValue()); return req; }).forEach(ossClient::deleteObjects); }
}
|
minio的实现:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75
|
import cn.hutool.core.date.DateUtil; import cn.hutool.core.io.file.FileNameUtil; import cn.hutool.core.lang.UUID; import cn.hutool.core.net.url.UrlBuilder; import cn.hutool.core.text.StrPool;
import io.minio.RemoveObjectsArgs; import io.minio.messages.DeleteObject; import jakarta.annotation.Resource; import org.apache.camel.ProducerTemplate; import org.apache.camel.component.minio.MinioConstants; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Lazy; import org.springframework.util.ObjectUtils;
import java.time.Duration; import java.util.List; import java.util.Map;
import static java.util.stream.Collectors.*;
public class MinioOssServiceImpl implements IOssService {
@Value("${camel.component.minio.presigned-url-expire}") private Duration presignedUrlExpire; @Resource private ProducerTemplate producerTemplate; @Lazy @Resource private IOssService ossService;
@Override public String getPresignedUrlPut(String bucket, String fileName) { var objectName = DateUtil.date().toDateStr() + FileNameUtil.UNIX_SEPARATOR + UUID.fastUUID() + DateUtil.date().toTimestamp() + StrPool.DOT + FileNameUtil.extName(fileName); return String.valueOf(producerTemplate.requestBodyAndHeaders( "direct:createUploadLink", "", Map.of(MinioConstants.BUCKET_NAME, bucket, MinioConstants.OBJECT_NAME, objectName, MinioConstants.PRESIGNED_URL_EXPIRATION_TIME, presignedUrlExpire))); }
@Override public void deleteBatch(List<String> fileUrls) { if (ObjectUtils.isEmpty(fileUrls)) { return; } var bucketObjectsMap = fileUrls.stream().map(path -> UrlBuilder.of(path).getPath()) .collect(groupingBy(path -> path.getSegment(0), mapping(path -> { path.getSegments().remove(0); return String.join(StrPool.SLASH, path.getSegments()); }, toList()))); bucketObjectsMap.entrySet().stream() .map(entry -> RemoveObjectsArgs.builder() .bucket(entry.getKey()) .objects(entry.getValue().stream().map(DeleteObject::new).toList()) ).parallel() .forEach(args -> producerTemplate.sendBody("direct:deleteBatch", args)); }
}
|
对应的service:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46
| import com.namaste.enums.GreenLabelEnum; import org.dromara.streamquery.stream.core.variable.BoolHelper;
import java.util.List;
public interface IOssService {
String getPresignedUrlPut(String bucket, String fileName);
void deleteBatch(List<String> fileUrls);
default GreenVO green(String img) { var result = GreenUtil.inspectImg(img, GreenLabelEnum.LIVE_STREAM_CHECK); var vo = GreenVO.of(result); if (BoolHelper.isFalsy(vo.getIsViolation())) { deleteBatch(List.of(img)); } return vo; }
}
|
test case
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84
| import cn.hutool.core.io.IoUtil; import cn.hutool.core.net.url.UrlBuilder; import cn.hutool.core.net.url.UrlQuery; import cn.hutool.core.util.URLUtil; import cn.hutool.http.ContentType; import cn.hutool.http.HttpUtil; import cn.hutool.http.Method; import jakarta.annotation.Resource; import lombok.SneakyThrows; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; import org.springframework.boot.test.context.SpringBootTest;
import java.io.FileNotFoundException; import java.util.List;
@SpringBootTest class OssServiceTest {
@Resource private IOssService ossService;
@Test @SneakyThrows void getUploadSTSAndDeleteBatchTest() { var presignedUrl = ossService.getPresignedUrlPut("test", "test.txt"); Assertions.assertNotNull(presignedUrl); var content = "Hello, Minio! Again!"; try (var response = HttpUtil.createRequest(Method.PUT, presignedUrl) .body(content, "application/octet-stream").execute()) { Assertions.assertTrue(response.isOk()); } var urlBuilder = UrlBuilder.of(presignedUrl).setQuery(new UrlQuery()); Assertions.assertEquals(content, IoUtil.readUtf8(urlBuilder.toURL().openStream())); ossService.deleteBatch(List.of(urlBuilder.toString())); Assertions.assertThrows(FileNotFoundException.class, () -> IoUtil.readUtf8(urlBuilder.toURL().openStream())); }
@Test void greenNormalTest() { var url = [foo]; var bytes = IoUtil.readBytes(URLUtil.getStream(URLUtil.url(url))); var preUrl = ossService.getPresignedUrlPut("test", "normal.jpg"); try (var response = HttpUtil.createRequest(Method.PUT, preUrl).contentType(ContentType.OCTET_STREAM.getValue()).body(bytes).execute()) { Assertions.assertTrue(response.isOk()); var urlBuilder = UrlBuilder.of(preUrl).setQuery(new UrlQuery()); Assertions.assertEquals(bytes.length, IoUtil.readBytes(URLUtil.getStream(urlBuilder.toURL())).length); var imgUrl = urlBuilder.toURL().toString(); var greenVO = ossService.green(imgUrl); Assertions.assertFalse(greenVO.getIsViolation()); Assertions.assertThrows(FileNotFoundException.class, () -> IoUtil.readUtf8(urlBuilder.toURL().openStream()));
} }
@Test void greenYellowTest() { var url = [bar]; var bytes = IoUtil.readBytes(URLUtil.getStream(URLUtil.url(url))); var preUrl = ossService.getPresignedUrlPut("test", "normal.jpg"); try (var response = HttpUtil.createRequest(Method.PUT, preUrl).body(bytes).execute()) { Assertions.assertTrue(response.isOk()); var urlBuilder = UrlBuilder.of(preUrl).setQuery(new UrlQuery()); Assertions.assertEquals(bytes.length, IoUtil.readBytes(URLUtil.getStream(urlBuilder.toURL())).length); var imgUrl = urlBuilder.toURL().toString(); var greenVO = ossService.green(imgUrl); Assertions.assertTrue(greenVO.getIsViolation()); var readBytes = IoUtil.readBytes(URLUtil.getStream(urlBuilder.toURL())); Assertions.assertEquals(readBytes.length, bytes.length); } }
}
|