Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ export function getApisS3OsHaloRunV1Alpha1ObjectsByPolicyName(params: GetApisS3O
continuationObject: params.continuationObject,
pageSize: params.pageSize,
unlinked: params.unlinked,
filePrefix: params.filePrefix,
};
return request.get<DeepRequired<S3ListResult>>(`/apis/s3os.halo.run/v1alpha1/objects/${params.policyName}`, {
params: paramsInput,
Expand All @@ -22,4 +23,5 @@ interface GetApisS3OsHaloRunV1Alpha1ObjectsByPolicyNameParams {
continuationObject?: any;
pageSize: any;
unlinked?: any;
filePrefix?: any;
}
4 changes: 3 additions & 1 deletion console/src/utils/request.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,9 @@ request.interceptors.response.use(
return Promise.reject(error);
}
const { status } = errorResponse;
if (status !== 200) {
if (status === 400) {
Toast.error(errorResponse.data.detail);
} else if (status !== 200) {
Toast.error("status: " + status);
}
return Promise.reject(error);
Expand Down
22 changes: 19 additions & 3 deletions console/src/views/S3Link.vue
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import {
VTag,
} from "@halo-dev/components";
import CarbonFolderDetailsReference from "~icons/carbon/folder-details-reference";
import IconErrorWarning from "~icons/ri/error-warning-line";
import {computed, onMounted, ref, watch} from "vue";
import {
getApisS3OsHaloRunV1Alpha1ObjectsByPolicyName,
Expand All @@ -31,6 +32,10 @@ const policyOptions = ref<{ label: string; value: string; attrs: any }[]>([{
value: "",
attrs: {disabled: true}
}]);
// update when fetch first page
const filePrefix = ref<string>("");
// update when user input
const filePrefixBind = ref<string>("");
const s3Objects = ref<S3ListResult>({
objects: [],
hasMore: false,
Expand Down Expand Up @@ -139,6 +144,8 @@ const clearTokenAndObject = () => {
s3Objects.value.nextContinuationObject = "";
};

// filePrefix will not be updated from user input
// if you want to update filePrefix, please call `handleFirstPage`
const fetchObjects = async () => {
if (!policyName.value) {
return;
Expand All @@ -152,6 +159,7 @@ const fetchObjects = async () => {
continuationToken: s3Objects.value.currentToken,
continuationObject: s3Objects.value.currentContinuationObject,
unlinked: selectedLinkedStatusItem.value,
filePrefix: filePrefix.value
});
if (objectsData.status == 200) {
s3Objects.value = objectsData.data;
Expand Down Expand Up @@ -222,6 +230,7 @@ const handleFirstPage = () => {
isFetching.value = true;
page.value = 1;
clearTokenAndObject();
filePrefix.value = filePrefixBind.value;
fetchObjects();
};

Expand Down Expand Up @@ -255,9 +264,9 @@ const handleModalClose = () => {
<div class="flex w-full flex-1 items-center sm:w-auto">
<div
v-if="!selectedFiles.length"
class="flex items-center gap-2"
class="flex flex-wrap items-center gap-2"
>
<span>存储策略:</span>
<span class="whitespace-nowrap">存储策略:</span>
<FormKit
id="policyChoose"
outer-class="!p-0"
Expand All @@ -266,8 +275,15 @@ const handleModalClose = () => {
name="policyName"
type="select"
:options="policyOptions"
@change="fetchObjects()"
@change="handleFirstPage"
></FormKit>
<icon-error-warning v-if="!policyName" class="text-red-500"/>
<SearchInput
v-model="filePrefixBind"
v-if="policyName"
placeholder="请输入文件名前缀搜索"
@update:modelValue="handleFirstPage"
></SearchInput>
</div>
<VSpace v-else>
<VButton type="primary" @click="handleLink">
Expand Down
8 changes: 4 additions & 4 deletions src/main/java/run/halo/s3os/S3LinkController.java
Original file line number Diff line number Diff line change
Expand Up @@ -28,13 +28,13 @@ public Mono<S3ListResult> listObjects(@PathVariable(value = "policyName") String
@RequestParam(name = "continuationToken", required = false) String continuationToken,
@RequestParam(name = "continuationObject", required = false) String continuationObject,
@RequestParam(name = "pageSize") Integer pageSize,
@RequestParam(name = "unlinked", required = false, defaultValue = "false")
Boolean unlinked) {
@RequestParam(name = "unlinked", required = false, defaultValue = "false") Boolean unlinked,
@RequestParam(name = "filePrefix", required = false) String filePrefix) {
if (unlinked) {
return s3LinkService.listObjectsUnlinked(policyName, continuationToken,
continuationObject, pageSize);
continuationObject, pageSize, filePrefix);
} else {
return s3LinkService.listObjects(policyName, continuationToken, pageSize);
return s3LinkService.listObjects(policyName, continuationToken, pageSize, filePrefix);
}
}

Expand Down
4 changes: 2 additions & 2 deletions src/main/java/run/halo/s3os/S3LinkService.java
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,10 @@ public interface S3LinkService {
Flux<Policy> listS3Policies();

Mono<S3ListResult> listObjects(String policyName, String continuationToken,
Integer pageSize);
Integer pageSize, String filePrefix);

Mono<LinkResult> addAttachmentRecords(String policyName, Set<String> objectKeys);

Mono<S3ListResult> listObjectsUnlinked(String policyName, String continuationToken,
String continuationObject, Integer pageSize);
String continuationObject, Integer pageSize, String filePrefix);
}
27 changes: 22 additions & 5 deletions src/main/java/run/halo/s3os/S3LinkServiceImpl.java
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ public Flux<Policy> listS3Policies() {

@Override
public Mono<S3ListResult> listObjects(String policyName, String continuationToken,
Integer pageSize) {
Integer pageSize, String filePrefix) {
return client.fetch(Policy.class, policyName)
.flatMap((policy) -> {
var configMapName = policy.getSpec().getConfigMapName();
Expand All @@ -68,11 +68,11 @@ public Mono<S3ListResult> listObjects(String policyName, String continuationToke
var properties = handler.getProperties(configMap);
var finalLocation = FilePathUtils.getFilePathByPlaceholder(properties.getLocation());
return Mono.using(() -> handler.buildS3Client(properties),
// 执行 listObjects
(s3Client) -> Mono.fromCallable(
() -> s3Client.listObjectsV2(ListObjectsV2Request.builder()
.bucket(properties.getBucket())
.prefix(StringUtils.isNotEmpty(finalLocation)
? finalLocation + "/" : null)
.prefix(buildPrefix(finalLocation, filePrefix))
.delimiter("/")
.maxKeys(pageSize)
.continuationToken(StringUtils.isNotEmpty(continuationToken)
Expand All @@ -81,10 +81,12 @@ public Mono<S3ListResult> listObjects(String policyName, String continuationToke
S3Client::close)
.flatMap(listObjectsV2Response -> {
List<S3Object> contents = listObjectsV2Response.contents();
// 过滤掉目录并转换为ObjectVo
var objectVos = contents
.stream().map(S3ListResult.ObjectVo::fromS3Object)
.filter(objectVo -> !objectVo.getKey().endsWith("/"))
.collect(Collectors.toMap(S3ListResult.ObjectVo::getKey, o -> o));
// 获取已经关联的附件并标记
ListOptions listOptions = new ListOptions();
listOptions.setFieldSelector(
FieldSelector.of(QueryFactory.equal("spec.policyName", policyName)));
Expand Down Expand Up @@ -163,7 +165,7 @@ private Flux<LinkResult.LinkResultItem> getLinkResultItems(Set<String> objectKey

@Override
public Mono<S3ListResult> listObjectsUnlinked(String policyName, String continuationToken,
String continuationObject, Integer pageSize) {
String continuationObject, Integer pageSize, String filePrefix) {
// TODO 优化成查一次数据库
return Mono.defer(() -> {
List<S3ListResult.ObjectVo> s3Objects = new ArrayList<>();
Expand All @@ -172,7 +174,8 @@ public Mono<S3ListResult> listObjectsUnlinked(String policyName, String continua

return Flux.defer(() -> Flux.just(
new TokenState(null, currToken.get() == null ? "" : currToken.get())))
.flatMap(tokenState -> listObjects(policyName, tokenState.nextToken, pageSize))
.flatMap(tokenState -> listObjects(policyName, tokenState.nextToken,
pageSize, filePrefix))
.flatMap(s3ListResult -> {
var filteredObjects = s3ListResult.getObjects();
if (!continuationObjectMatched.get()) {
Expand Down Expand Up @@ -267,4 +270,18 @@ private <T> Mono<T> authenticationConsumer(Function<Authentication, Mono<T>> fun
.flatMap(func);
}

String buildPrefix(String finalLocation, String filePrefix) {
if (StringUtils.isBlank(finalLocation) && StringUtils.isBlank(filePrefix)) {
return null;
}
StringBuilder sb = new StringBuilder();
if (StringUtils.isNotBlank(finalLocation)) {
sb.append(finalLocation).append("/");
}
if (StringUtils.isNotBlank(filePrefix)) {
sb.append(filePrefix);
}
return sb.toString();
}

}