This is an automated email from the ASF dual-hosted git repository.

casion pushed a commit to branch dev-1.9.0
in repository https://gitbox.apache.org/repos/asf/linkis.git


The following commit(s) were added to refs/heads/dev-1.9.0 by this push:
     new 2759fdcfcc The result set supports field truncation (#5297)
2759fdcfcc is described below

commit 2759fdcfcc3525fa9f27a47d13e517ceb67c39b1
Author: v-kkhuang <[email protected]>
AuthorDate: Thu Mar 26 10:21:40 2026 +0800

    The result set supports field truncation (#5297)
---
 .../storage/entity/FieldTruncationResult.java      |  73 +++
 .../linkis/storage/entity/OversizedFieldInfo.java  |  68 +++
 .../apache/linkis/storage/utils/ResultUtils.java   | 544 +++++++++++++++++++++
 .../linkis/storage/conf/LinkisStorageConf.scala    |  29 ++
 .../linkis/storage/excel/StorageExcelWriter.scala  |  42 ++
 .../resultset/table/TableResultDeserializer.scala  |  16 +-
 .../pipeline/constant/PipeLineConstant.scala       |   3 +
 .../pipeline/executor/CSVExecutor.scala            |  71 ++-
 .../pipeline/executor/ExcelExecutor.scala          | 143 ++++--
 .../executor/PipelineEngineConnExecutor.scala      |  20 +-
 .../filesystem/restful/api/FsRestfulApi.java       | 257 +++++-----
 11 files changed, 1076 insertions(+), 190 deletions(-)

diff --git 
a/linkis-commons/linkis-storage/src/main/java/org/apache/linkis/storage/entity/FieldTruncationResult.java
 
b/linkis-commons/linkis-storage/src/main/java/org/apache/linkis/storage/entity/FieldTruncationResult.java
new file mode 100644
index 0000000000..6760d95d9d
--- /dev/null
+++ 
b/linkis-commons/linkis-storage/src/main/java/org/apache/linkis/storage/entity/FieldTruncationResult.java
@@ -0,0 +1,73 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.linkis.storage.entity;
+
+import java.util.List;
+
+/** Result of field truncation detection and processing */
+public class FieldTruncationResult {
+  private boolean hasOversizedFields;
+  private List<OversizedFieldInfo> oversizedFields;
+  private Integer maxOversizedFieldCount;
+  private List<String[]> data;
+
+  public FieldTruncationResult() {}
+
+  public FieldTruncationResult(
+      boolean hasOversizedFields,
+      List<OversizedFieldInfo> oversizedFields,
+      Integer maxOversizedFieldCount,
+      List<String[]> data) {
+    this.hasOversizedFields = hasOversizedFields;
+    this.oversizedFields = oversizedFields;
+    this.maxOversizedFieldCount = maxOversizedFieldCount;
+    this.data = data;
+  }
+
+  public boolean isHasOversizedFields() {
+    return hasOversizedFields;
+  }
+
+  public void setHasOversizedFields(boolean hasOversizedFields) {
+    this.hasOversizedFields = hasOversizedFields;
+  }
+
+  public List<OversizedFieldInfo> getOversizedFields() {
+    return oversizedFields;
+  }
+
+  public void setOversizedFields(List<OversizedFieldInfo> oversizedFields) {
+    this.oversizedFields = oversizedFields;
+  }
+
+  public Integer getMaxOversizedFieldCount() {
+    return maxOversizedFieldCount;
+  }
+
+  public void setMaxOversizedFieldCount(Integer maxOversizedFieldCount) {
+    this.maxOversizedFieldCount = maxOversizedFieldCount;
+  }
+
+  public List<String[]> getData() {
+    return data;
+  }
+
+  public void setData(List<String[]> data) {
+    this.data = data;
+  }
+}
diff --git 
a/linkis-commons/linkis-storage/src/main/java/org/apache/linkis/storage/entity/OversizedFieldInfo.java
 
b/linkis-commons/linkis-storage/src/main/java/org/apache/linkis/storage/entity/OversizedFieldInfo.java
new file mode 100644
index 0000000000..f1fd1b985b
--- /dev/null
+++ 
b/linkis-commons/linkis-storage/src/main/java/org/apache/linkis/storage/entity/OversizedFieldInfo.java
@@ -0,0 +1,68 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.linkis.storage.entity;
+
+/** Represents information about an oversized field in a result set */
+public class OversizedFieldInfo {
+  private String fieldName;
+  private Integer rowIndex;
+  private Integer actualLength;
+  private Integer maxLength;
+
+  public OversizedFieldInfo() {}
+
+  public OversizedFieldInfo(
+      String fieldName, Integer rowIndex, Integer actualLength, Integer 
maxLength) {
+    this.fieldName = fieldName;
+    this.rowIndex = rowIndex;
+    this.actualLength = actualLength;
+    this.maxLength = maxLength;
+  }
+
+  public String getFieldName() {
+    return fieldName;
+  }
+
+  public void setFieldName(String fieldName) {
+    this.fieldName = fieldName;
+  }
+
+  public Integer getRowIndex() {
+    return rowIndex;
+  }
+
+  public void setRowIndex(Integer rowIndex) {
+    this.rowIndex = rowIndex;
+  }
+
+  public Integer getActualLength() {
+    return actualLength;
+  }
+
+  public void setActualLength(Integer actualLength) {
+    this.actualLength = actualLength;
+  }
+
+  public Integer getMaxLength() {
+    return maxLength;
+  }
+
+  public void setMaxLength(Integer maxLength) {
+    this.maxLength = maxLength;
+  }
+}
diff --git 
a/linkis-commons/linkis-storage/src/main/java/org/apache/linkis/storage/utils/ResultUtils.java
 
b/linkis-commons/linkis-storage/src/main/java/org/apache/linkis/storage/utils/ResultUtils.java
new file mode 100644
index 0000000000..3b8a051143
--- /dev/null
+++ 
b/linkis-commons/linkis-storage/src/main/java/org/apache/linkis/storage/utils/ResultUtils.java
@@ -0,0 +1,544 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.linkis.storage.utils;
+
+import org.apache.linkis.common.io.FsWriter;
+import org.apache.linkis.storage.conf.LinkisStorageConf;
+import org.apache.linkis.storage.entity.FieldTruncationResult;
+import org.apache.linkis.storage.entity.OversizedFieldInfo;
+import org.apache.linkis.storage.excel.StorageExcelWriter;
+import org.apache.linkis.storage.resultset.table.TableMetaData;
+import org.apache.linkis.storage.resultset.table.TableRecord;
+import org.apache.linkis.storage.source.FileSource;
+
+import org.apache.commons.lang3.StringUtils;
+import org.apache.commons.math3.util.Pair;
+
+import java.io.IOException;
+import java.text.MessageFormat;
+import java.util.*;
+import java.util.function.Predicate;
+import java.util.stream.Collectors;
+import java.util.stream.IntStream;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class ResultUtils {
+
+  public static final Logger LOGGER = 
LoggerFactory.getLogger(ResultUtils.class);
+  /**
+   * 删除指定字段的内容
+   *
+   * @param metadata 元数据数组,包含字段信息
+   * @param contentList 需要处理的二维字符串数组
+   * @param fieldsToRemove 需要删除的字段集合
+   * @return 处理后的字符串数组,若输入无效返回空集合而非null
+   */
+  @SuppressWarnings("unchecked")
+  public static List<String[]> removeFieldsFromContent(
+      Object metadata, List<String[]> contentList, Set<String> fieldsToRemove) 
{
+    // 1. 参数校验
+    if (metadata == null
+        || fieldsToRemove == null
+        || fieldsToRemove.isEmpty()
+        || contentList == null
+        || !(metadata instanceof Map[])) {
+      return contentList;
+    }
+
+    // 2. 安全类型转换
+    Map<String, Object>[] fieldMetadata = (Map<String, Object>[]) metadata;
+
+    // 3. 收集需要删除的列索引(去重并排序)
+    List<Integer> columnsToRemove =
+        IntStream.range(0, fieldMetadata.length)
+            .filter(
+                i -> {
+                  Map<String, Object> meta = fieldMetadata[i];
+                  Object columnName = meta.get("columnName");
+                  return columnName != null
+                      && 
fieldsToRemove.contains(columnName.toString().toLowerCase());
+                })
+            .distinct()
+            .boxed()
+            .sorted((a, b) -> Integer.compare(b, a))
+            .collect(Collectors.toList());
+
+    // 如果没有需要删除的列,直接返回副本
+    if (columnsToRemove.isEmpty()) {
+      return new ArrayList<>(contentList);
+    }
+    // 4. 对每行数据进行处理(删除指定列)
+    return contentList.stream()
+        .map(
+            row -> {
+              if (row == null || row.length == 0) {
+                return row;
+              }
+              // 创建可变列表以便删除元素
+              List<String> rowList = new ArrayList<>(Arrays.asList(row));
+              // 从后向前删除列,避免索引变化问题
+              for (int columnIndex : columnsToRemove) {
+                if (columnIndex < rowList.size()) {
+                  rowList.remove(columnIndex);
+                  LOGGER.info("MaskedField  Remove Data columnIndex:" + 
columnIndex);
+                }
+              }
+              return rowList.toArray(new String[0]);
+            })
+        .collect(Collectors.toList());
+  }
+
+  @SuppressWarnings("unchecked")
+  public static Map[] filterMaskedFieldsFromMetadata(Object metadata, 
Set<String> maskedFields) {
+    // 1. 参数校验
+    if (metadata == null || maskedFields == null || !(metadata instanceof 
Map[])) {
+      return new Map[0];
+    }
+
+    // 2. 类型转换(已通过校验,可安全强转)
+    Map<String, Object>[] originalMaps = (Map<String, Object>[]) metadata;
+
+    // 3. 过滤逻辑(提取谓词增强可读性)
+    Predicate<Map<String, Object>> isNotMaskedField =
+        map -> 
!maskedFields.contains(map.get("columnName").toString().toLowerCase());
+
+    // 4. 流处理 + 结果转换
+    return Arrays.stream(originalMaps)
+        .filter(isNotMaskedField)
+        .toArray(Map[]::new); // 等价于 toArray(new Map[0])
+  }
+
+  /**
+   * Convert Map array to TableMetaData
+   *
+   * @param metadataArray Array of Map containing column information
+   * @return TableMetaData object
+   */
+  @SuppressWarnings("unchecked")
+  public static TableMetaData convertMapArrayToTableMetaData(Map[] 
metadataArray) {
+    if (metadataArray == null || metadataArray.length == 0) {
+      return new TableMetaData(new org.apache.linkis.storage.domain.Column[0]);
+    }
+
+    org.apache.linkis.storage.domain.Column[] columns =
+        new org.apache.linkis.storage.domain.Column[metadataArray.length];
+
+    for (int i = 0; i < metadataArray.length; i++) {
+      Map<String, Object> columnMap = (Map<String, Object>) metadataArray[i];
+      String columnName =
+          columnMap.get("columnName") != null ? 
columnMap.get("columnName").toString() : "";
+      String dataType =
+          columnMap.get("dataType") != null ? 
columnMap.get("dataType").toString() : "string";
+      String comment = columnMap.get("comment") != null ? 
columnMap.get("comment").toString() : "";
+
+      // Create Column object
+      org.apache.linkis.storage.domain.DataType dtype =
+          
org.apache.linkis.storage.domain.DataType$.MODULE$.toDataType(dataType);
+      columns[i] = new org.apache.linkis.storage.domain.Column(columnName, 
dtype, comment);
+    }
+
+    return new TableMetaData(columns);
+  }
+
+  public static void dealMaskedField(
+      String maskedFieldNames, FsWriter<?, ?> fsWriter, FileSource fileSource) 
throws IOException {
+
+    LOGGER.info("Applying field masking for fields: {}", maskedFieldNames);
+
+    // Parse masked field names
+    Set<String> maskedFieldsSet =
+        Arrays.stream(maskedFieldNames.split(","))
+            .map(String::trim)
+            .map(String::toLowerCase)
+            .filter(StringUtils::isNotBlank)
+            .collect(Collectors.toSet());
+
+    // Collect data from file source
+    Pair<Object, ArrayList<String[]>>[] collectedData = fileSource.collect();
+
+    // Process each result set
+    for (int i = 0; i < collectedData.length; i++) {
+      Pair<Object, ArrayList<String[]>> collectedDataSet = collectedData[i];
+      Object metadata = collectedDataSet.getFirst();
+      ArrayList<String[]> content = collectedDataSet.getSecond();
+
+      // Filter metadata and content
+      Map[] filteredMetadata = filterMaskedFieldsFromMetadata(metadata, 
maskedFieldsSet);
+      List<String[]> filteredContent = removeFieldsFromContent(metadata, 
content, maskedFieldsSet);
+
+      // Convert Map[] to TableMetaData
+      TableMetaData tableMetaData = 
convertMapArrayToTableMetaData(filteredMetadata);
+
+      // Write filtered data
+      fsWriter.addMetaData(tableMetaData);
+      for (String[] row : filteredContent) {
+        fsWriter.addRecord(new TableRecord(row));
+      }
+      LOGGER.info(
+          "Field masking applied for result set {}. Original columns: {}, 
Filtered columns: {}",
+          i,
+          ((Map[]) metadata).length,
+          filteredMetadata.length);
+    }
+  }
+
+  /**
+   * Detect and handle oversized fields in result set
+   *
+   * @param metadata Column names list
+   * @param FileContent Data rows list (each row is an ArrayList or Object[])
+   * @param truncate Whether to truncate (false means detection only)
+   * @return FieldTruncationResult containing detection results and processed 
data
+   */
+  public static FieldTruncationResult detectAndHandle(
+      Object metadata, List<String[]> FileContent, Integer maxLength, boolean 
truncate) {
+    if (metadata == null || !(metadata instanceof Map[])) {
+      return new FieldTruncationResult();
+    }
+
+    // 2. 类型转换(已通过校验,可安全强转)
+    Map<String, Object>[] originalMaps = (Map<String, Object>[]) metadata;
+
+    // 提取列名
+    List<String> columnNames = new ArrayList<>();
+    if (metadata != null) {
+      for (Map meta : originalMaps) {
+        Object columnName = meta.get("columnName");
+        columnNames.add(columnName != null ? columnName.toString() : "");
+      }
+    }
+
+    // 转换 String[] 数组为 ArrayList<String>
+    List<ArrayList<String>> dataList = new ArrayList<>();
+    for (String[] row : FileContent) {
+      ArrayList<String> rowList = new ArrayList<>(Arrays.asList(row));
+      dataList.add(rowList);
+    }
+
+    int maxCount = LinkisStorageConf.OVERSIZED_FIELD_MAX_COUNT();
+
+    // Detect oversized fields
+    List<OversizedFieldInfo> oversizedFields =
+        detectOversizedFields(columnNames, dataList, maxLength, maxCount);
+
+    boolean hasOversizedFields = !oversizedFields.isEmpty();
+
+    // Truncate if requested
+    List<ArrayList<String>> processedData = dataList;
+    LOGGER.info(
+        "Staring Field truncation detection function ,truncate is 
{},hasOversizedFields {}",
+        truncate,
+        hasOversizedFields);
+    if (truncate && hasOversizedFields) {
+      processedData = truncateFields(columnNames, dataList, maxLength);
+    }
+    List<String[]> convertedList =
+        processedData.stream()
+            .map(row -> row != null ? row.toArray(new String[0]) : null)
+            .collect(Collectors.toList());
+    return new FieldTruncationResult(hasOversizedFields, oversizedFields, 
maxCount, convertedList);
+  }
+
+  public static void detectAndHandle(
+      StorageExcelWriter fsWriter, FileSource fileSource, Integer maxLength) 
throws IOException {
+    // Collect data from file source
+    Pair<Object, ArrayList<String[]>>[] collectedData = fileSource.collect();
+
+    // Process each result set
+    for (int i = 0; i < collectedData.length; i++) {
+      Pair<Object, ArrayList<String[]>> collectedDataSet = collectedData[i];
+      Object metadata = collectedDataSet.getFirst();
+      ArrayList<String[]> content = collectedDataSet.getSecond();
+
+      FieldTruncationResult fieldTruncationResult =
+          detectAndHandle(metadata, content, maxLength, true);
+
+      List<String[]> data = fieldTruncationResult.getData();
+
+      // Convert Map[] to TableMetaData and add truncation markers for 
oversized fields
+      TableMetaData tableMetaData =
+          convertMapArrayToTableMetaData((Map<String, Object>[]) metadata);
+      // Create a set of oversized field names for quick lookup
+      List<String> oversizedFieldNames =
+          fieldTruncationResult.getOversizedFields().stream()
+              .map(OversizedFieldInfo::getFieldName)
+              .distinct()
+              .collect(Collectors.toList());
+      // If there are oversized fields, add markers to column names in the 
metadata
+      if (fieldTruncationResult.isHasOversizedFields()
+          && fieldTruncationResult.getOversizedFields() != null) {
+        // Update column names to indicate truncation with max length
+        org.apache.linkis.storage.domain.Column[] columns = 
tableMetaData.columns();
+        for (int j = 0; j < columns.length; j++) {
+          if (oversizedFieldNames.contains(columns[j].columnName())) {
+            // Get the max length for this field
+            String truncatedInfo =
+                maxLength != null ? "(truncated to " + maxLength + " chars)" : 
"(truncated)";
+            // Create a new column with truncation info suffix to indicate 
truncation
+            columns[j] =
+                new org.apache.linkis.storage.domain.Column(
+                    columns[j].columnName() + truncatedInfo,
+                    columns[j].dataType(),
+                    columns[j].comment());
+          }
+        }
+
+        // Create new TableMetaData with updated column names
+        tableMetaData = new TableMetaData(columns);
+      }
+      // Write filtered data
+      if (oversizedFieldNames.isEmpty()) {
+        fsWriter.addMetaData(tableMetaData);
+      } else {
+        StringJoiner joiner = new StringJoiner(",");
+        oversizedFieldNames.forEach(joiner::add);
+        String note =
+            MessageFormat.format(
+                "结果集存在字段值超过{0}字符,无法全量下载,以下字段截取前{0}字符展示:{1}",
+                LinkisStorageConf.FIELD_EXPORT_DOWNLOAD_LENGTH(), joiner);
+        fsWriter.addMetaDataWithNote(tableMetaData, note);
+      }
+      for (String[] row : data) {
+        fsWriter.addRecord(new TableRecord(row));
+      }
+    }
+  }
+
+  /**
+   * Detect oversized fields
+   *
+   * @param metadata Column names
+   * @param dataList Data rows
+   * @param maxLength Max length threshold
+   * @param maxCount Max number of oversized fields to collect
+   * @return List of oversized field info
+   */
+  private static List<OversizedFieldInfo> detectOversizedFields(
+      List<String> metadata, List<ArrayList<String>> dataList, int maxLength, 
int maxCount) {
+
+    List<OversizedFieldInfo> oversizedFields = new ArrayList<>();
+
+    if (metadata == null || dataList == null || dataList.isEmpty()) {
+      return oversizedFields;
+    }
+
+    // 使用Set来存储已经检查过的超长字段名,避免重复检查
+    Set<String> detectedOversizedFields = new HashSet<>();
+
+    // Iterate through data rows
+    for (int rowIndex = 0; rowIndex < dataList.size(); rowIndex++) {
+
+      ArrayList<String> row = dataList.get(rowIndex);
+      if (row == null) {
+        continue;
+      }
+
+      // Check each field in the row
+      for (int colIndex = 0; colIndex < row.size() && colIndex < 
metadata.size(); colIndex++) {
+
+        String fieldName = metadata.get(colIndex);
+
+        // 如果该字段已经被检测为超长字段,则跳过检查,提高效率
+        if (detectedOversizedFields.contains(fieldName)) {
+          continue;
+        }
+
+        String fieldValue = row.get(colIndex);
+        int fieldLength = getFieldLength(fieldValue);
+
+        if (fieldLength > maxLength) {
+          oversizedFields.add(new OversizedFieldInfo(fieldName, rowIndex, 
fieldLength, maxLength));
+          // 将超长字段名加入Set,避免重复检查
+          detectedOversizedFields.add(fieldName);
+          LOGGER.info(
+              "Detected oversized field: field={}, row={}, actualLength={}, 
maxLength={}",
+              fieldName,
+              rowIndex,
+              fieldLength,
+              maxLength);
+        }
+      }
+    }
+
+    return oversizedFields;
+  }
+
+  /**
+   * Truncate oversized fields
+   *
+   * @param metadata Column names
+   * @param dataList Data rows
+   * @param maxLength Max length
+   * @return Truncated data list
+   */
+  private static List<ArrayList<String>> truncateFields(
+      List<String> metadata, List<ArrayList<String>> dataList, int maxLength) {
+
+    if (dataList == null || dataList.isEmpty()) {
+      return dataList;
+    }
+
+    List<ArrayList<String>> truncatedData = new ArrayList<>();
+
+    for (ArrayList<String> row : dataList) {
+      if (row == null) {
+        truncatedData.add(null);
+        continue;
+      }
+
+      ArrayList<String> truncatedRow = new ArrayList<>();
+      for (String fieldValue : row) {
+        String truncatedValue = truncateFieldValue(fieldValue, maxLength);
+        truncatedRow.add(truncatedValue);
+      }
+      truncatedData.add(truncatedRow);
+    }
+
+    return truncatedData;
+  }
+
+  /**
+   * Get field value character length
+   *
+   * @param value Field value
+   * @return Character length
+   */
+  private static int getFieldLength(Object value) {
+    if (value == null) {
+      return 0;
+    }
+    return value.toString().length();
+  }
+
+  /**
+   * Truncate single field value
+   *
+   * @param value Field value
+   * @param maxLength Max length
+   * @return Truncated value
+   */
+  private static String truncateFieldValue(Object value, int maxLength) {
+    if (value == null) {
+      return null;
+    }
+    String str = value.toString();
+    if (str.length() <= maxLength) {
+      return str;
+    }
+    return str.substring(0, maxLength);
+  }
+
+  /**
+   * Apply both field masking and truncation
+   *
+   * @param maskedFieldNames Comma-separated list of field names to mask
+   * @param fsWriter The FsWriter to write results to
+   * @param fileSource The FileSource to read data from
+   * @throws IOException
+   */
+  public static void applyFieldMaskingAndTruncation(
+      String maskedFieldNames,
+      StorageExcelWriter fsWriter,
+      FileSource fileSource,
+      Integer maxLength)
+      throws IOException {
+
+    LOGGER.info("Applying both field masking and truncation");
+    // First collect data from file source
+    Pair<Object, ArrayList<String[]>>[] collectedData = fileSource.collect();
+
+    // Process each result set
+    for (int i = 0; i < collectedData.length; i++) {
+      Pair<Object, ArrayList<String[]>> collectedDataSet = collectedData[i];
+      Object metadata = collectedDataSet.getFirst();
+      ArrayList<String[]> content = collectedDataSet.getSecond();
+
+      // Apply field masking
+      Set<String> maskedFieldsSet =
+          Arrays.stream(maskedFieldNames.split(","))
+              .map(String::trim)
+              .map(String::toLowerCase)
+              .filter(StringUtils::isNotBlank)
+              .collect(Collectors.toSet());
+
+      Map[] filteredMetadata = filterMaskedFieldsFromMetadata(metadata, 
maskedFieldsSet);
+      List<String[]> filteredContent = removeFieldsFromContent(metadata, 
content, maskedFieldsSet);
+
+      // Then apply field truncation
+      FieldTruncationResult fieldTruncationResult =
+          detectAndHandle(filteredMetadata, filteredContent, maxLength, true);
+      List<String[]> finalData = fieldTruncationResult.getData();
+
+      // Write data
+      TableMetaData tableMetaData = 
convertMapArrayToTableMetaData(filteredMetadata);
+      // Create a set of oversized field names for quick lookup
+      List<String> oversizedFieldNames =
+          fieldTruncationResult.getOversizedFields().stream()
+              .map(OversizedFieldInfo::getFieldName)
+              .distinct()
+              .collect(Collectors.toList());
+      // If there are oversized fields, add markers to column names in the 
metadata
+      if (fieldTruncationResult.isHasOversizedFields()
+          && fieldTruncationResult.getOversizedFields() != null) {
+        // Update column names to indicate truncation with max length
+        org.apache.linkis.storage.domain.Column[] columns = 
tableMetaData.columns();
+        for (int j = 0; j < columns.length; j++) {
+          if (oversizedFieldNames.contains(columns[j].columnName())) {
+            // Get the max length for this field
+            String truncatedInfo =
+                maxLength != null
+                    ? 
MessageFormat.format(LinkisStorageConf.FIELD_TRUNCATION_NOTE(), maxLength)
+                    : LinkisStorageConf.FIELD_NOT_TRUNCATION_NOTE();
+            // Create a new column with truncation info suffix to indicate 
truncation
+            columns[j] =
+                new org.apache.linkis.storage.domain.Column(
+                    columns[j].columnName() + truncatedInfo,
+                    columns[j].dataType(),
+                    columns[j].comment());
+          }
+        }
+
+        // Create new TableMetaData with updated column names
+        tableMetaData = new TableMetaData(columns);
+      }
+      if (oversizedFieldNames.isEmpty()) {
+        fsWriter.addMetaData(tableMetaData);
+      } else {
+        StringJoiner joiner = new StringJoiner(",");
+        oversizedFieldNames.forEach(joiner::add);
+        String note =
+            MessageFormat.format(
+                LinkisStorageConf.FIELD_OPEN_FILE_TRUNCATION_NOTE(),
+                LinkisStorageConf.FIELD_EXPORT_DOWNLOAD_LENGTH(),
+                joiner);
+        fsWriter.addMetaDataWithNote(tableMetaData, note);
+      }
+      for (String[] row : finalData) {
+        fsWriter.addRecord(new TableRecord(row));
+      }
+      LOGGER.info(
+          "Field masking and truncation applied for result set {}. Original 
columns: {}, Filtered columns: {}, Truncated fields: {}",
+          i,
+          ((Map[]) metadata).length,
+          filteredMetadata.length,
+          fieldTruncationResult.getOversizedFields().size());
+    }
+  }
+}
diff --git 
a/linkis-commons/linkis-storage/src/main/scala/org/apache/linkis/storage/conf/LinkisStorageConf.scala
 
b/linkis-commons/linkis-storage/src/main/scala/org/apache/linkis/storage/conf/LinkisStorageConf.scala
index 50c60fecd2..a28ede48df 100644
--- 
a/linkis-commons/linkis-storage/src/main/scala/org/apache/linkis/storage/conf/LinkisStorageConf.scala
+++ 
b/linkis-commons/linkis-storage/src/main/scala/org/apache/linkis/storage/conf/LinkisStorageConf.scala
@@ -83,4 +83,33 @@ object LinkisStorageConf {
   val LINKIS_READ_ROW_BYTE_MAX_LEN =
     ByteTimeUtils.byteStringAsBytes(LINKIS__READ_RESULT_ROW_MAX_LEN_STR)
 
+  val FIELD_TRUNCATION_ENABLED =
+    CommonVars("linkis.resultset.field.truncation.enabled", false).getValue
+
+  val FIELD_MASKED_ENABLED =
+    CommonVars("linkis.resultset.field.masked.enabled", false).getValue
+
+  val FIELD_VIEW_MAX_LENGTH = 
CommonVars("linkis.resultset.field.view.max.length", 10000).getValue
+
+  val FIELD_EXPORT_DOWNLOAD_LENGTH =
+    CommonVars("linkis.resultset.field.download.max.length", 32767).getValue
+
+  val FIELD_EXPORT_MAX_LENGTH =
+    CommonVars("linkis.resultset.field.export.max.length", 32767).getValue
+
+  val OVERSIZED_FIELD_MAX_COUNT =
+    CommonVars("linkis.resultset.field.oversized.max.count", 20).getValue
+
+  val FIELD_TRUNCATION_NOTE =
+    CommonVars("linkis.resultset.field.truncation.excel.note", "(truncated to 
{0} chars)").getValue
+
+  val FIELD_NOT_TRUNCATION_NOTE =
+    CommonVars("linkis.resultset.field.truncation.default.note", 
"(truncated)").getValue
+
+  val FIELD_OPEN_FILE_TRUNCATION_NOTE =
+    CommonVars(
+      "linkis.resultset.field.truncation.note",
+      "结果集存在字段值超过{0}字符,无法全量下载,以下字段截取前{0}字符展示:{1}"
+    ).getValue
+
 }
diff --git 
a/linkis-commons/linkis-storage/src/main/scala/org/apache/linkis/storage/excel/StorageExcelWriter.scala
 
b/linkis-commons/linkis-storage/src/main/scala/org/apache/linkis/storage/excel/StorageExcelWriter.scala
index 9ea83130df..8baeb792e2 100644
--- 
a/linkis-commons/linkis-storage/src/main/scala/org/apache/linkis/storage/excel/StorageExcelWriter.scala
+++ 
b/linkis-commons/linkis-storage/src/main/scala/org/apache/linkis/storage/excel/StorageExcelWriter.scala
@@ -24,6 +24,7 @@ import 
org.apache.linkis.storage.resultset.table.{TableMetaData, TableRecord}
 
 import org.apache.commons.io.IOUtils
 import org.apache.poi.ss.usermodel._
+import org.apache.poi.ss.util.CellRangeAddress
 import org.apache.poi.xssf.streaming.{SXSSFCell, SXSSFSheet, SXSSFWorkbook}
 
 import java.io._
@@ -68,6 +69,15 @@ class StorageExcelWriter(
     headerCellStyle
   }
 
+  def getWarningStyle: CellStyle = {
+    val warningFont = workBook.createFont
+    warningFont.setBold(true)
+    warningFont.setColor(IndexedColors.RED.getIndex)
+    val warningCellStyle = workBook.createCellStyle
+    warningCellStyle.setFont(warningFont)
+    warningCellStyle
+  }
+
   def getWorkBook: Workbook = {
     // 自适应列宽
     sheet.trackAllColumnsForAutoSizing()
@@ -133,6 +143,38 @@ class StorageExcelWriter(
     rowPoint += 1
   }
 
+  @scala.throws[IOException]
+  def addMetaDataWithNote(metaData: MetaData, note: String): Unit = {
+    init
+    // 创建公告行(第0行)
+    val noticeRow = sheet.createRow(0)
+    val noticeCell = noticeRow.createCell(0)
+    noticeCell.setCellValue(note)
+    noticeCell.setCellStyle(getWarningStyle)
+
+    // 合并单元格(从第0列到最后一列)
+    val columns = metaData.asInstanceOf[TableMetaData].columns
+    val columnCount = columns.length
+    if (columnCount > 1) {
+      val mergeRange = new CellRangeAddress(0, 0, 0, columnCount - 1)
+      sheet.addMergedRegion(mergeRange)
+    }
+
+    // 创建表头行(第1行)
+    val tableHead = sheet.createRow(1)
+    val columnType = new ArrayBuffer[DataType]()
+    columnCounter = 0
+    for (elem <- columns) {
+      val headCell = tableHead.createCell(columnCounter)
+      headCell.setCellValue(elem.columnName)
+      headCell.setCellStyle(getDefaultHeadStyle)
+      columnType += elem.dataType
+      columnCounter += 1
+    }
+    types = columnType.toArray
+    rowPoint += 2 // 由于增加了公告行,所以行指针需要增加2(公告行和表头行)
+  }
+
   @scala.throws[IOException]
   override def addRecord(record: Record): Unit = {
     // TODO: 是否需要替换null值
diff --git 
a/linkis-commons/linkis-storage/src/main/scala/org/apache/linkis/storage/resultset/table/TableResultDeserializer.scala
 
b/linkis-commons/linkis-storage/src/main/scala/org/apache/linkis/storage/resultset/table/TableResultDeserializer.scala
index 86d09e9532..323d816c9b 100644
--- 
a/linkis-commons/linkis-storage/src/main/scala/org/apache/linkis/storage/resultset/table/TableResultDeserializer.scala
+++ 
b/linkis-commons/linkis-storage/src/main/scala/org/apache/linkis/storage/resultset/table/TableResultDeserializer.scala
@@ -127,14 +127,16 @@ class TableResultDeserializer extends 
ResultDeserializer[TableMetaData, TableRec
       val len = colArray(i).toInt
       val res = Dolphin.getString(bytes, index, len)
       if (res.length > LinkisStorageConf.LINKIS_RESULT_COL_LENGTH && 
enableLimit) {
-        throw new ColLengthExceedException(
-          LinkisStorageErrorCodeSummary.RESULT_COL_LENGTH.getErrorCode,
-          MessageFormat.format(
-            LinkisStorageErrorCodeSummary.RESULT_COL_LENGTH.getErrorDesc,
-            res.length.asInstanceOf[Object],
-            LinkisStorageConf.LINKIS_RESULT_COL_LENGTH.asInstanceOf[Object]
+        if (!LinkisStorageConf.FIELD_TRUNCATION_ENABLED) {
+          throw new ColLengthExceedException(
+            LinkisStorageErrorCodeSummary.RESULT_COL_LENGTH.getErrorCode,
+            MessageFormat.format(
+              LinkisStorageErrorCodeSummary.RESULT_COL_LENGTH.getErrorDesc,
+              res.length.asInstanceOf[Object],
+              LinkisStorageConf.LINKIS_RESULT_COL_LENGTH.asInstanceOf[Object]
+            )
           )
-        )
+        }
       }
       index += len
       // 如果enableLimit为true,则采取的是列分页
diff --git 
a/linkis-engineconn-plugins/pipeline/src/main/scala/org/apache/linkis/manager/engineplugin/pipeline/constant/PipeLineConstant.scala
 
b/linkis-engineconn-plugins/pipeline/src/main/scala/org/apache/linkis/manager/engineplugin/pipeline/constant/PipeLineConstant.scala
index 77c2a3a8a1..477addcfff 100644
--- 
a/linkis-engineconn-plugins/pipeline/src/main/scala/org/apache/linkis/manager/engineplugin/pipeline/constant/PipeLineConstant.scala
+++ 
b/linkis-engineconn-plugins/pipeline/src/main/scala/org/apache/linkis/manager/engineplugin/pipeline/constant/PipeLineConstant.scala
@@ -30,4 +30,7 @@ object PipeLineConstant {
     "wds.linkis.engine.pipeline.field.quote.retoch.enable"
 
   val BLANK = "BLANK"
+
+  val PIPELINE_MASKED_CONF = "pipeline.masked.field.names"
+
 }
diff --git 
a/linkis-engineconn-plugins/pipeline/src/main/scala/org/apache/linkis/manager/engineplugin/pipeline/executor/CSVExecutor.scala
 
b/linkis-engineconn-plugins/pipeline/src/main/scala/org/apache/linkis/manager/engineplugin/pipeline/executor/CSVExecutor.scala
index 68b5010f17..9f4a7833fa 100644
--- 
a/linkis-engineconn-plugins/pipeline/src/main/scala/org/apache/linkis/manager/engineplugin/pipeline/executor/CSVExecutor.scala
+++ 
b/linkis-engineconn-plugins/pipeline/src/main/scala/org/apache/linkis/manager/engineplugin/pipeline/executor/CSVExecutor.scala
@@ -18,6 +18,7 @@
 package org.apache.linkis.manager.engineplugin.pipeline.executor
 
 import org.apache.linkis.common.io.FsPath
+import org.apache.linkis.common.utils.Logging
 import 
org.apache.linkis.engineconn.computation.executor.execute.EngineExecutionContext
 import 
org.apache.linkis.manager.engineplugin.pipeline.conf.PipelineEngineConfiguration.{
   PIPELINE_FIELD_QUOTE_RETOUCH_ENABLE,
@@ -25,6 +26,7 @@ import 
org.apache.linkis.manager.engineplugin.pipeline.conf.PipelineEngineConfig
   PIPELINE_OUTPUT_CHARSET_STR,
   PIPELINE_OUTPUT_ISOVERWRITE_SWITCH
 }
+import 
org.apache.linkis.manager.engineplugin.pipeline.constant.PipeLineConstant
 import 
org.apache.linkis.manager.engineplugin.pipeline.constant.PipeLineConstant._
 import 
org.apache.linkis.manager.engineplugin.pipeline.errorcode.PopelineErrorCodeSummary._
 import 
org.apache.linkis.manager.engineplugin.pipeline.exception.PipeLineErrorException
@@ -32,13 +34,15 @@ import org.apache.linkis.scheduler.executer.ExecuteResponse
 import org.apache.linkis.storage.FSFactory
 import org.apache.linkis.storage.csv.CSVFsWriter
 import org.apache.linkis.storage.source.FileSource
+import org.apache.linkis.storage.utils.ResultUtils
 import 
org.apache.linkis.storage.utils.StorageConfiguration.STORAGE_RS_FILE_SUFFIX
 
 import org.apache.commons.io.IOUtils
+import org.apache.commons.lang3.StringUtils
 
 import java.io.OutputStream
 
-class CSVExecutor extends PipeLineExecutor {
+class CSVExecutor extends PipeLineExecutor with Logging {
 
   override def execute(
       sourcePath: String,
@@ -57,35 +61,58 @@ class CSVExecutor extends PipeLineExecutor {
         NOT_A_RESULT_SET_FILE.getErrorDesc
       )
     }
+
+    // Extract masked field names from options
+    val maskedFieldNames = 
options.getOrDefault(PipeLineConstant.PIPELINE_MASKED_CONF, "")
+
     val sourceFsPath = new FsPath(sourcePath)
     val destFsPath = new FsPath(destPath)
     val sourceFs = FSFactory.getFs(sourceFsPath)
     sourceFs.init(null)
     val destFs = FSFactory.getFs(destFsPath)
     destFs.init(null)
-    val fileSource = FileSource.create(sourceFsPath, sourceFs)
-    if (!FileSource.isTableResultSet(fileSource)) {
-      throw new PipeLineErrorException(
-        ONLY_RESULT_CONVERTED_TO_CSV.getErrorCode,
-        ONLY_RESULT_CONVERTED_TO_CSV.getErrorDesc
+
+    try {
+      val fileSource = FileSource.create(sourceFsPath, sourceFs)
+      if (!FileSource.isTableResultSet(fileSource)) {
+        throw new PipeLineErrorException(
+          ONLY_RESULT_CONVERTED_TO_CSV.getErrorCode,
+          ONLY_RESULT_CONVERTED_TO_CSV.getErrorDesc
+        )
+      }
+
+      var nullValue = options.getOrDefault(PIPELINE_OUTPUT_SHUFFLE_NULL_TYPE, 
"NULL")
+      if (BLANK.equalsIgnoreCase(nullValue)) nullValue = ""
+
+      val outputStream: OutputStream =
+        destFs.write(destFsPath, 
PIPELINE_OUTPUT_ISOVERWRITE_SWITCH.getValue(options))
+      OutputStreamCache.osCache.put(engineExecutionContext.getJobId.get, 
outputStream)
+
+      val cSVFsWriter = CSVFsWriter.getCSVFSWriter(
+        PIPELINE_OUTPUT_CHARSET_STR.getValue(options),
+        PIPELINE_FIELD_SPLIT_STR.getValue(options),
+        PIPELINE_FIELD_QUOTE_RETOUCH_ENABLE.getValue(options),
+        outputStream
       )
+
+      try {
+        if (StringUtils.isNotBlank(maskedFieldNames)) {
+          // Apply field masking if maskedFieldNames is provided
+          ResultUtils.dealMaskedField(maskedFieldNames, cSVFsWriter, 
fileSource)
+        } else {
+          // Original stream write logic
+          logger.info("No field masking, using stream write for CSV export")
+          fileSource.addParams("nullValue", nullValue).write(cSVFsWriter)
+        }
+      } finally {
+        IOUtils.closeQuietly(cSVFsWriter)
+        IOUtils.closeQuietly(fileSource)
+      }
+    } finally {
+      IOUtils.closeQuietly(sourceFs)
+      IOUtils.closeQuietly(destFs)
     }
-    var nullValue = options.getOrDefault(PIPELINE_OUTPUT_SHUFFLE_NULL_TYPE, 
"NULL")
-    if (BLANK.equalsIgnoreCase(nullValue)) nullValue = ""
-    val outputStream: OutputStream =
-      destFs.write(destFsPath, 
PIPELINE_OUTPUT_ISOVERWRITE_SWITCH.getValue(options))
-    OutputStreamCache.osCache.put(engineExecutionContext.getJobId.get, 
outputStream)
-    val cSVFsWriter = CSVFsWriter.getCSVFSWriter(
-      PIPELINE_OUTPUT_CHARSET_STR.getValue(options),
-      PIPELINE_FIELD_SPLIT_STR.getValue(options),
-      PIPELINE_FIELD_QUOTE_RETOUCH_ENABLE.getValue(options),
-      outputStream
-    )
-    fileSource.addParams("nullValue", nullValue).write(cSVFsWriter)
-    IOUtils.closeQuietly(cSVFsWriter)
-    IOUtils.closeQuietly(fileSource)
-    IOUtils.closeQuietly(sourceFs)
-    IOUtils.closeQuietly(destFs)
+
     super.execute(sourcePath, destPath, engineExecutionContext)
   }
 
diff --git 
a/linkis-engineconn-plugins/pipeline/src/main/scala/org/apache/linkis/manager/engineplugin/pipeline/executor/ExcelExecutor.scala
 
b/linkis-engineconn-plugins/pipeline/src/main/scala/org/apache/linkis/manager/engineplugin/pipeline/executor/ExcelExecutor.scala
index 42c0e27cd2..3d6d924c4e 100644
--- 
a/linkis-engineconn-plugins/pipeline/src/main/scala/org/apache/linkis/manager/engineplugin/pipeline/executor/ExcelExecutor.scala
+++ 
b/linkis-engineconn-plugins/pipeline/src/main/scala/org/apache/linkis/manager/engineplugin/pipeline/executor/ExcelExecutor.scala
@@ -18,33 +18,41 @@
 package org.apache.linkis.manager.engineplugin.pipeline.executor
 
 import org.apache.linkis.common.io.FsPath
-import org.apache.linkis.common.utils.ResultSetUtils
+import org.apache.linkis.common.utils.{Logging, ResultSetUtils}
 import 
org.apache.linkis.engineconn.computation.executor.execute.EngineExecutionContext
 import 
org.apache.linkis.manager.engineplugin.pipeline.conf.PipelineEngineConfiguration
 import 
org.apache.linkis.manager.engineplugin.pipeline.conf.PipelineEngineConfiguration.PIPELINE_OUTPUT_ISOVERWRITE_SWITCH
+import 
org.apache.linkis.manager.engineplugin.pipeline.constant.PipeLineConstant
 import 
org.apache.linkis.manager.engineplugin.pipeline.constant.PipeLineConstant._
 import 
org.apache.linkis.manager.engineplugin.pipeline.errorcode.PopelineErrorCodeSummary._
 import 
org.apache.linkis.manager.engineplugin.pipeline.exception.PipeLineErrorException
 import org.apache.linkis.scheduler.executer.ExecuteResponse
 import org.apache.linkis.storage.FSFactory
-import org.apache.linkis.storage.excel.{ExcelFsWriter, StorageMultiExcelWriter}
+import org.apache.linkis.storage.conf.LinkisStorageConf
+import 
org.apache.linkis.storage.conf.LinkisStorageConf.FIELD_TRUNCATION_ENABLED
+import org.apache.linkis.storage.excel.{ExcelFsWriter, StorageExcelWriter, 
StorageMultiExcelWriter}
 import org.apache.linkis.storage.fs.FileSystem
 import org.apache.linkis.storage.source.FileSource
+import org.apache.linkis.storage.utils.ResultUtils
 
 import org.apache.commons.io.IOUtils
+import org.apache.commons.lang3.StringUtils
 
 import java.io.OutputStream
 import java.util
 
-import scala.collection.JavaConverters.mapAsScalaMapConverter
+import scala.collection.JavaConverters._
 
-class ExcelExecutor extends PipeLineExecutor {
+class ExcelExecutor extends PipeLineExecutor with Logging {
 
   override def execute(
       sourcePath: String,
       destPath: String,
       engineExecutorContext: EngineExecutionContext
   ): ExecuteResponse = {
+    // Extract masked field names from options
+    val maskedFieldNames = 
options.getOrDefault(PipeLineConstant.PIPELINE_MASKED_CONF, "")
+
     var fileSource: FileSource = null
     var excelFsWriter: ExcelFsWriter = null
     val sourceFsPath = new FsPath(sourcePath)
@@ -53,56 +61,93 @@ class ExcelExecutor extends PipeLineExecutor {
     sourceFs.init(null)
     val destFs = FSFactory.getFs(destFsPath)
     destFs.init(null)
-    val outputStream: OutputStream =
-      destFs.write(destFsPath, 
PIPELINE_OUTPUT_ISOVERWRITE_SWITCH.getValue(options))
-    val paramsMap = new util.HashMap[String, String]()
-    engineExecutorContext.getProperties.asScala
-      .filter(_._2 != null)
-      .map(kv => (kv._1, kv._2.toString))
-      .foreach(kv => paramsMap.put(kv._1, kv._2))
-    val excelAutoFormat = 
PipelineEngineConfiguration.EXPORT_EXCEL_AUTO_FORMAT.getValue(paramsMap)
-    if (sourcePath.contains(".")) {
-      // sourcePaht 是文件形式
-      // TODO: fs 加目录判断
-      if (!FileSource.isResultSet(sourcePath)) {
+
+    try {
+      val outputStream: OutputStream =
+        destFs.write(destFsPath, 
PIPELINE_OUTPUT_ISOVERWRITE_SWITCH.getValue(options))
+      val paramsMap = new util.HashMap[String, String]()
+      engineExecutorContext.getProperties.asScala
+        .filter(_._2 != null)
+        .map(kv => (kv._1, kv._2.toString))
+        .foreach(kv => paramsMap.put(kv._1, kv._2))
+      val excelAutoFormat =
+        
PipelineEngineConfiguration.EXPORT_EXCEL_AUTO_FORMAT.getValue(paramsMap)
+      if (sourcePath.contains(".")) {
+        // sourcePaht 是文件形式
+        // TODO: fs 加目录判断
+        if (!FileSource.isResultSet(sourcePath)) {
+          throw new PipeLineErrorException(
+            NOT_A_RESULT_SET_FILE.getErrorCode,
+            NOT_A_RESULT_SET_FILE.getErrorDesc
+          )
+        }
+        fileSource = FileSource.create(sourceFsPath, sourceFs)
+        excelFsWriter = ExcelFsWriter.getExcelFsWriter(
+          DEFAULTC_HARSET,
+          DEFAULT_SHEETNAME,
+          DEFAULT_DATEFORMATE,
+          outputStream,
+          excelAutoFormat
+        )
+      } else {
+        // 目录形式
+        excelFsWriter = new StorageMultiExcelWriter(outputStream, 
excelAutoFormat)
+        val fsPathListWithError =
+          sourceFs.asInstanceOf[FileSystem].listPathWithError(sourceFsPath)
+        if (fsPathListWithError == null) {
+          throw new PipeLineErrorException(EMPTY_DIR.getErrorCode, 
EMPTY_DIR.getErrorDesc)
+        }
+        val fsPathList = fsPathListWithError.getFsPaths
+        ResultSetUtils.sortByNameNum(fsPathList)
+        fileSource = FileSource.create(fsPathList.toArray(Array[FsPath]()), 
sourceFs)
+      }
+      if (!FileSource.isTableResultSet(fileSource)) {
         throw new PipeLineErrorException(
-          NOT_A_RESULT_SET_FILE.getErrorCode,
-          NOT_A_RESULT_SET_FILE.getErrorDesc
+          ONLY_RESULT_CONVERTED_TO_EXCEL.getErrorCode,
+          ONLY_RESULT_CONVERTED_TO_EXCEL.getErrorDesc
         )
       }
-      fileSource = FileSource.create(sourceFsPath, sourceFs)
-      excelFsWriter = ExcelFsWriter.getExcelFsWriter(
-        DEFAULTC_HARSET,
-        DEFAULT_SHEETNAME,
-        DEFAULT_DATEFORMATE,
-        outputStream,
-        excelAutoFormat
-      )
-    } else {
-      // 目录形式
-      excelFsWriter = new StorageMultiExcelWriter(outputStream, 
excelAutoFormat)
-      val fsPathListWithError = 
sourceFs.asInstanceOf[FileSystem].listPathWithError(sourceFsPath)
-      if (fsPathListWithError == null) {
-        throw new PipeLineErrorException(EMPTY_DIR.getErrorCode, 
EMPTY_DIR.getErrorDesc)
+
+      var nullValue = options.getOrDefault(PIPELINE_OUTPUT_SHUFFLE_NULL_TYPE, 
"NULL")
+      if (BLANK.equalsIgnoreCase(nullValue)) nullValue = ""
+      OutputStreamCache.osCache.put(engineExecutorContext.getJobId.get, 
outputStream)
+
+      try {
+        // Apply field masking if maskedFieldNames is provided
+        fileSource.addParams("nullValue", nullValue)
+        // 如果同时提供了字段屏蔽和字段截取参数,则先执行字段屏蔽,再执行字段截取
+        if (StringUtils.isNotBlank(maskedFieldNames) && 
FIELD_TRUNCATION_ENABLED) {
+          // 同时执行字段屏蔽和字段截取
+          ResultUtils.applyFieldMaskingAndTruncation(
+            maskedFieldNames,
+            excelFsWriter.asInstanceOf[StorageExcelWriter],
+            fileSource,
+            LinkisStorageConf.FIELD_EXPORT_MAX_LENGTH
+          )
+        } else if (StringUtils.isNotBlank(maskedFieldNames)) {
+          // 只执行字段屏蔽
+          ResultUtils.dealMaskedField(maskedFieldNames, excelFsWriter, 
fileSource)
+        } else if (FIELD_TRUNCATION_ENABLED) {
+          // 只执行字段截取
+          ResultUtils.detectAndHandle(
+            excelFsWriter.asInstanceOf[StorageExcelWriter],
+            fileSource,
+            LinkisStorageConf.FIELD_EXPORT_MAX_LENGTH
+          )
+        } else {
+          // Original stream write logic
+          logger.info("No field masking, using stream write for Excel export")
+          fileSource.write(excelFsWriter)
+        }
+      } finally {
+        IOUtils.closeQuietly(excelFsWriter)
+        IOUtils.closeQuietly(fileSource)
       }
-      val fsPathList = fsPathListWithError.getFsPaths
-      ResultSetUtils.sortByNameNum(fsPathList)
-      fileSource = FileSource.create(fsPathList.toArray(Array[FsPath]()), 
sourceFs)
+    } finally {
+      IOUtils.closeQuietly(sourceFs)
+      IOUtils.closeQuietly(destFs)
     }
-    if (!FileSource.isTableResultSet(fileSource)) {
-      throw new PipeLineErrorException(
-        ONLY_RESULT_CONVERTED_TO_EXCEL.getErrorCode,
-        ONLY_RESULT_CONVERTED_TO_EXCEL.getErrorDesc
-      )
-    }
-    var nullValue = options.getOrDefault(PIPELINE_OUTPUT_SHUFFLE_NULL_TYPE, 
"NULL")
-    if (BLANK.equalsIgnoreCase(nullValue)) nullValue = ""
-    OutputStreamCache.osCache.put(engineExecutorContext.getJobId.get, 
outputStream)
-    fileSource.addParams("nullValue", nullValue).write(excelFsWriter)
-    IOUtils.closeQuietly(excelFsWriter)
-    IOUtils.closeQuietly(fileSource)
-    IOUtils.closeQuietly(sourceFs)
-    IOUtils.closeQuietly(destFs)
+
     super.execute(sourcePath, destPath, engineExecutorContext)
   }
 
diff --git 
a/linkis-engineconn-plugins/pipeline/src/main/scala/org/apache/linkis/manager/engineplugin/pipeline/executor/PipelineEngineConnExecutor.scala
 
b/linkis-engineconn-plugins/pipeline/src/main/scala/org/apache/linkis/manager/engineplugin/pipeline/executor/PipelineEngineConnExecutor.scala
index da1bd0e6e1..f22e2ce6ba 100644
--- 
a/linkis-engineconn-plugins/pipeline/src/main/scala/org/apache/linkis/manager/engineplugin/pipeline/executor/PipelineEngineConnExecutor.scala
+++ 
b/linkis-engineconn-plugins/pipeline/src/main/scala/org/apache/linkis/manager/engineplugin/pipeline/executor/PipelineEngineConnExecutor.scala
@@ -30,12 +30,14 @@ import org.apache.linkis.manager.common.entity.resource.{
 }
 import org.apache.linkis.manager.engineplugin.common.conf.EngineConnPluginConf
 import org.apache.linkis.manager.engineplugin.common.util.NodeResourceUtils
+import 
org.apache.linkis.manager.engineplugin.pipeline.constant.PipeLineConstant
 import 
org.apache.linkis.manager.engineplugin.pipeline.errorcode.PopelineErrorCodeSummary._
 import 
org.apache.linkis.manager.engineplugin.pipeline.exception.PipeLineErrorException
 import org.apache.linkis.manager.label.entity.Label
 import org.apache.linkis.protocol.engine.JobProgressInfo
 import org.apache.linkis.rpc.Sender
 import org.apache.linkis.scheduler.executer.ExecuteResponse
+import org.apache.linkis.storage.conf.LinkisStorageConf
 
 import java.util
 
@@ -66,11 +68,25 @@ class PipelineEngineConnExecutor(val id: Int) extends 
ComputationExecutor with L
       newOptions.put(keyAndValue._1, keyAndValue._2.toString)
     }
     newOptions.asScala.foreach({ case (k, v) => logger.info(s"key is $k, value 
is $v") })
-    val regex = "(?i)\\s*from\\s+(\\S+)\\s+to\\s+(\\S+)\\s?".r
+
+    // Regex patterns for Pipeline syntax
+    val regexWithMask = 
"(?i)\\s*from\\s+(\\S+)\\s+to\\s+(\\S+)\\s+without\\s+\"([^\"]+)\"\\s*".r
+    val regexNormal = "(?i)\\s*from\\s+(\\S+)\\s+to\\s+(\\S+)\\s*".r
+
     try {
       thread = Thread.currentThread()
       code match {
-        case regex(sourcePath, destPath) =>
+        case regexWithMask(sourcePath, destPath, maskedFields) =>
+          logger.info(s"Pipeline execution with field masking: $maskedFields")
+          val enhancedOptions = new util.HashMap[String, String](newOptions)
+          if (LinkisStorageConf.FIELD_MASKED_ENABLED) {
+            enhancedOptions.put(PipeLineConstant.PIPELINE_MASKED_CONF, 
maskedFields)
+          }
+          PipelineExecutorSelector
+            .select(sourcePath, destPath, 
enhancedOptions.asInstanceOf[util.Map[String, String]])
+            .execute(sourcePath, destPath, engineExecutorContext)
+        case regexNormal(sourcePath, destPath) =>
+          logger.info("Pipeline execution without field masking")
           PipelineExecutorSelector
             .select(sourcePath, destPath, 
newOptions.asInstanceOf[util.Map[String, String]])
             .execute(sourcePath, destPath, engineExecutorContext)
diff --git 
a/linkis-public-enhancements/linkis-pes-publicservice/src/main/java/org/apache/linkis/filesystem/restful/api/FsRestfulApi.java
 
b/linkis-public-enhancements/linkis-pes-publicservice/src/main/java/org/apache/linkis/filesystem/restful/api/FsRestfulApi.java
index 0cf8d8334f..90a60de51b 100644
--- 
a/linkis-public-enhancements/linkis-pes-publicservice/src/main/java/org/apache/linkis/filesystem/restful/api/FsRestfulApi.java
+++ 
b/linkis-public-enhancements/linkis-pes-publicservice/src/main/java/org/apache/linkis/filesystem/restful/api/FsRestfulApi.java
@@ -40,12 +40,14 @@ import org.apache.linkis.server.utils.ModuleUserUtils;
 import org.apache.linkis.storage.conf.LinkisStorageConf;
 import org.apache.linkis.storage.csv.CSVFsWriter;
 import org.apache.linkis.storage.domain.FsPathListWithError;
+import org.apache.linkis.storage.entity.FieldTruncationResult;
 import org.apache.linkis.storage.excel.*;
 import org.apache.linkis.storage.exception.ColLengthExceedException;
 import org.apache.linkis.storage.fs.FileSystem;
 import org.apache.linkis.storage.script.*;
 import org.apache.linkis.storage.source.FileSource;
 import org.apache.linkis.storage.source.FileSource$;
+import org.apache.linkis.storage.utils.ResultUtils;
 import org.apache.linkis.storage.utils.StorageUtils;
 
 import org.apache.commons.collections.CollectionUtils;
@@ -71,9 +73,7 @@ import java.nio.file.Paths;
 import java.text.MessageFormat;
 import java.util.*;
 import java.util.concurrent.CompletableFuture;
-import java.util.function.Predicate;
 import java.util.stream.Collectors;
-import java.util.stream.IntStream;
 
 import com.fasterxml.jackson.databind.JsonNode;
 import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
@@ -635,7 +635,8 @@ public class FsRestfulApi {
       @RequestParam(value = "columnPage", required = false, defaultValue = 
"1") Integer columnPage,
       @RequestParam(value = "columnPageSize", required = false, defaultValue = 
"500")
           Integer columnPageSize,
-      @RequestParam(value = "maskedFieldNames", required = false) String 
maskedFieldNames)
+      @RequestParam(value = "maskedFieldNames", required = false) String 
maskedFieldNames,
+      @RequestParam(value = "truncateColumn", required = false) String 
truncateColumn)
       throws IOException, WorkSpaceException {
 
     Message message = Message.ok();
@@ -663,6 +664,23 @@ public class FsRestfulApi {
 
     int[] columnIndices = null;
     FileSource fileSource = null;
+    String zh_msg =
+        MessageFormat.format(
+            
"结果集存在字段值字符数超过{0},如需查看全部数据请导出文件或使用字符串截取函数(substring、substr)截取相关字符即可前端展示数据内容",
+            LinkisStorageConf.LINKIS_RESULT_COL_LENGTH());
+    String en_msg =
+        MessageFormat.format(
+            "There is a field value exceed {0} characters or col size exceed 
{1} in the result set. If you want to view it, please use the result set export 
function.",
+            LinkisStorageConf.LINKIS_RESULT_COL_LENGTH(),
+            LinkisStorageConf.LINKIS_RESULT_COLUMN_SIZE());
+    String truncateColumn_msg =
+        MessageFormat.format(
+            "结果集存在字段值字符数超过{0},如需查看全部数据请导出文件或确认截取展示数据内容",
+            LinkisStorageConf.LINKIS_RESULT_COL_LENGTH());
+    String truncateColumn_en_msg =
+        MessageFormat.format(
+            "The result set contains field values exceeding {0} characters. To 
view the full data, please export the file or confirm the displayed content is 
truncated",
+            LinkisStorageConf.LINKIS_RESULT_COL_LENGTH());
     try {
       fileSource = FileSource$.MODULE$.create(fsPath, fileSystem);
       if (nullValue != null && BLANK.equalsIgnoreCase(nullValue)) {
@@ -737,16 +755,65 @@ public class FsRestfulApi {
         }
         // 增加字段屏蔽
         Object resultmap = newMap == null ? metaMap : newMap;
-        if (FileSource$.MODULE$.isResultSet(fsPath.getPath())
-            && StringUtils.isNotBlank(maskedFieldNames)) {
-          // 如果结果集并且屏蔽字段不为空,则执行屏蔽逻辑,反之则保持原逻辑
-          Set<String> maskedFields =
-              new 
HashSet<>(Arrays.asList(maskedFieldNames.toLowerCase().split(",")));
-          Map[] metadata = filterMaskedFieldsFromMetadata(resultmap, 
maskedFields);
-          List<String[]> fileContent =
-              removeFieldsFromContent(resultmap, result.getSecond(), 
maskedFields);
-          message.data("metadata", metadata).data("fileContent", fileContent);
+        if (FileSource$.MODULE$.isResultSet(fsPath.getPath()) && (resultmap 
instanceof Map[])) {
+          // 2. 类型转换(已通过校验,可安全强转)
+          Map<String, Object>[] filteredMetadata = (Map<String, Object>[]) 
resultmap;
+          List<String[]> filteredContent = result.getSecond();
+          // 优先过滤屏蔽字段
+          if (LinkisStorageConf.FIELD_MASKED_ENABLED()
+              && StringUtils.isNotBlank(maskedFieldNames)) {
+            Set<String> maskedFields =
+                new 
HashSet<>(Arrays.asList(maskedFieldNames.toLowerCase().split(",")));
+            filteredMetadata = 
ResultUtils.filterMaskedFieldsFromMetadata(resultmap, maskedFields);
+            filteredContent =
+                ResultUtils.removeFieldsFromContent(resultmap, 
filteredContent, maskedFields);
+          }
+          // 优先截取大字段
+          if (LinkisStorageConf.FIELD_TRUNCATION_ENABLED()) {
+            FieldTruncationResult fieldTruncationResult =
+                ResultUtils.detectAndHandle(
+                    filteredMetadata,
+                    filteredContent,
+                    LinkisStorageConf.FIELD_VIEW_MAX_LENGTH(),
+                    false);
+            if (fieldTruncationResult.isHasOversizedFields()) {
+              // 检测到超长字段
+              if (null == truncateColumn) {
+                message.data("oversizedFields", 
fieldTruncationResult.getOversizedFields());
+                message.data("zh_msg", truncateColumn_msg);
+                message.data("en_msg", truncateColumn_en_msg);
+                return message;
+              }
+              boolean truncateColumnSwitch = 
Boolean.parseBoolean(truncateColumn);
+              if (truncateColumnSwitch) {
+                // 用户选择截取
+                FieldTruncationResult truncationResult =
+                    ResultUtils.detectAndHandle(
+                        filteredMetadata,
+                        filteredContent,
+                        LinkisStorageConf.FIELD_VIEW_MAX_LENGTH(),
+                        truncateColumnSwitch);
+                filteredContent = truncationResult.getData();
+
+              } else {
+                // 用户未选择截取,提示用户
+                message.data("type", fileSource.getFileSplits()[0].type());
+                message.data("display_prohibited", true);
+                message.data("zh_msg", zh_msg);
+                message.data("en_msg", en_msg);
+                return message;
+              }
+            }
+          }
+          if (StringUtils.isNotBlank(maskedFieldNames)
+              || LinkisStorageConf.FIELD_TRUNCATION_ENABLED()) {
+            message.data("metadata", filteredMetadata).data("fileContent", 
filteredContent);
+          } else {
+            // 不执行字段屏蔽也不执行字段截取
+            message.data("metadata", resultmap).data("fileContent", 
result.getSecond());
+          }
         } else {
+          // 不执行字段屏蔽也不执行字段截取
           message.data("metadata", resultmap).data("fileContent", 
result.getSecond());
         }
         message.data("type", fileSource.getFileSplits()[0].type());
@@ -756,17 +823,8 @@ public class FsRestfulApi {
         LOGGER.info("Failed to open file {}", path, e);
         message.data("type", fileSource.getFileSplits()[0].type());
         message.data("display_prohibited", true);
-        message.data(
-            "zh_msg",
-            MessageFormat.format(
-                
"结果集存在字段值字符数超过{0},如需查看全部数据请导出文件或使用字符串截取函数(substring、substr)截取相关字符即可前端展示数据内容",
-                LinkisStorageConf.LINKIS_RESULT_COL_LENGTH()));
-        message.data(
-            "en_msg",
-            MessageFormat.format(
-                "There is a field value exceed {0} characters or col size 
exceed {1} in the result set. If you want to view it, please use the result set 
export function.",
-                LinkisStorageConf.LINKIS_RESULT_COL_LENGTH(),
-                LinkisStorageConf.LINKIS_RESULT_COLUMN_SIZE()));
+        message.data("zh_msg", zh_msg);
+        message.data("en_msg", en_msg);
         return message;
       }
     } finally {
@@ -778,87 +836,6 @@ public class FsRestfulApi {
       IOUtils.closeQuietly(fileSource);
     }
   }
-  /**
-   * 删除指定字段的内容
-   *
-   * @param metadata 元数据数组,包含字段信息
-   * @param contentList 需要处理的二维字符串数组
-   * @param fieldsToRemove 需要删除的字段集合
-   * @return 处理后的字符串数组,若输入无效返回空集合而非null
-   */
-  @SuppressWarnings("unchecked")
-  private List<String[]> removeFieldsFromContent(
-      Object metadata, List<String[]> contentList, Set<String> fieldsToRemove) 
{
-    // 1. 参数校验
-    if (metadata == null
-        || fieldsToRemove == null
-        || fieldsToRemove.isEmpty()
-        || contentList == null
-        || !(metadata instanceof Map[])) {
-      return contentList;
-    }
-
-    // 2. 安全类型转换
-    Map<String, Object>[] fieldMetadata = (Map<String, Object>[]) metadata;
-
-    // 3. 收集需要删除的列索引(去重并排序)
-    List<Integer> columnsToRemove =
-        IntStream.range(0, fieldMetadata.length)
-            .filter(
-                i -> {
-                  Map<String, Object> meta = fieldMetadata[i];
-                  Object columnName = meta.get("columnName");
-                  return columnName != null
-                      && 
fieldsToRemove.contains(columnName.toString().toLowerCase());
-                })
-            .distinct()
-            .boxed()
-            .sorted((a, b) -> Integer.compare(b, a))
-            .collect(Collectors.toList());
-
-    // 如果没有需要删除的列,直接返回副本
-    if (columnsToRemove.isEmpty()) {
-      return new ArrayList<>(contentList);
-    }
-    // 4. 对每行数据进行处理(删除指定列)
-    return contentList.stream()
-        .map(
-            row -> {
-              if (row == null || row.length == 0) {
-                return row;
-              }
-              // 创建可变列表以便删除元素
-              List<String> rowList = new ArrayList<>(Arrays.asList(row));
-              // 从后向前删除列,避免索引变化问题
-              for (int columnIndex : columnsToRemove) {
-                if (columnIndex < rowList.size()) {
-                  rowList.remove(columnIndex);
-                }
-              }
-              return rowList.toArray(new String[0]);
-            })
-        .collect(Collectors.toList());
-  }
-
-  @SuppressWarnings("unchecked")
-  private Map[] filterMaskedFieldsFromMetadata(Object metadata, Set<String> 
maskedFields) {
-    // 1. 参数校验
-    if (metadata == null || maskedFields == null || !(metadata instanceof 
Map[])) {
-      return new Map[0];
-    }
-
-    // 2. 类型转换(已通过校验,可安全强转)
-    Map<String, Object>[] originalMaps = (Map<String, Object>[]) metadata;
-
-    // 3. 过滤逻辑(提取谓词增强可读性)
-    Predicate<Map<String, Object>> isNotMaskedField =
-        map -> 
!maskedFields.contains(map.get("columnName").toString().toLowerCase());
-
-    // 4. 流处理 + 结果转换
-    return Arrays.stream(originalMaps)
-        .filter(isNotMaskedField)
-        .toArray(Map[]::new); // 等价于 toArray(new Map[0])
-  }
 
   /**
    * 组装获取列索引
@@ -970,7 +947,12 @@ public class FsRestfulApi {
         dataType = "String",
         defaultValue = "NULL"),
     @ApiImplicitParam(name = "limit", required = true, dataType = "Integer", 
defaultValue = "0"),
-    @ApiImplicitParam(name = "autoFormat", dataType = "Boolean")
+    @ApiImplicitParam(name = "autoFormat", dataType = "Boolean"),
+    @ApiImplicitParam(
+        name = "maskedFieldNames",
+        required = false,
+        dataType = "String",
+        value = "Comma-separated list of field names to mask (e.g. 
password,apikey)")
   })
   @RequestMapping(path = "resultsetToExcel", method = RequestMethod.GET)
   public void resultsetToExcel(
@@ -988,7 +970,8 @@ public class FsRestfulApi {
       @RequestParam(value = "nullValue", defaultValue = "NULL") String 
nullValue,
       @RequestParam(value = "limit", defaultValue = "0") Integer limit,
       @RequestParam(value = "autoFormat", defaultValue = "false") Boolean 
autoFormat,
-      @RequestParam(value = "keepNewline", defaultValue = "false") Boolean 
keepNewline)
+      @RequestParam(value = "keepNewline", defaultValue = "false") Boolean 
keepNewline,
+      @RequestParam(value = "maskedFieldNames", required = false) String 
maskedFieldNames)
       throws WorkSpaceException, IOException {
     ServletOutputStream outputStream = null;
     FsWriter fsWriter = null;
@@ -1064,7 +1047,32 @@ public class FsRestfulApi {
         default:
           throw WorkspaceExceptionManager.createException(80015);
       }
-      fileSource.write(fsWriter);
+
+      // 如果同时提供了字段屏蔽和字段截取参数,则先执行字段屏蔽,再执行字段截取
+      if (LinkisStorageConf.FIELD_MASKED_ENABLED()
+          && StringUtils.isNotBlank(maskedFieldNames)
+          && LinkisStorageConf.FIELD_TRUNCATION_ENABLED()
+          && outputFileType.equals("xlsx")) {
+        // 同时执行字段屏蔽和字段截取
+        StorageExcelWriter excelFsWriter = (StorageExcelWriter) fsWriter;
+        ResultUtils.applyFieldMaskingAndTruncation(
+            maskedFieldNames,
+            excelFsWriter,
+            fileSource,
+            LinkisStorageConf.FIELD_EXPORT_DOWNLOAD_LENGTH());
+      } else if (LinkisStorageConf.FIELD_MASKED_ENABLED()
+          && StringUtils.isNotBlank(maskedFieldNames)) {
+        // 只执行字段屏蔽
+        ResultUtils.dealMaskedField(maskedFieldNames, fsWriter, fileSource);
+      } else if (LinkisStorageConf.FIELD_TRUNCATION_ENABLED() && 
outputFileType.equals("xlsx")) {
+        // 只执行字段截取
+        StorageExcelWriter excelFsWriter = (StorageExcelWriter) fsWriter;
+        ResultUtils.detectAndHandle(
+            excelFsWriter, fileSource, 
LinkisStorageConf.FIELD_EXPORT_DOWNLOAD_LENGTH());
+      } else {
+        // Original stream write logic
+        fileSource.write(fsWriter);
+      }
       fsWriter.flush();
       LOGGER.info("userName {} Finished to resultsetToExcel File {}", 
userName, path);
     } catch (Exception e) {
@@ -1103,7 +1111,12 @@ public class FsRestfulApi {
         dataType = "String",
         defaultValue = "NULL"),
     @ApiImplicitParam(name = "limit", required = true, dataType = "Integer", 
defaultValue = "0"),
-    @ApiImplicitParam(name = "autoFormat", dataType = "Boolean")
+    @ApiImplicitParam(name = "autoFormat", dataType = "Boolean"),
+    @ApiImplicitParam(
+        name = "maskedFieldNames",
+        required = false,
+        dataType = "String",
+        value = "Comma-separated list of field names to mask (e.g. 
password,apikey)")
   })
   @RequestMapping(path = "resultsetsToExcel", method = RequestMethod.GET)
   public void resultsetsToExcel(
@@ -1114,7 +1127,8 @@ public class FsRestfulApi {
           String outputFileName,
       @RequestParam(value = "nullValue", defaultValue = "NULL") String 
nullValue,
       @RequestParam(value = "limit", defaultValue = "0") Integer limit,
-      @RequestParam(value = "autoFormat", defaultValue = "false") Boolean 
autoFormat)
+      @RequestParam(value = "autoFormat", defaultValue = "false") Boolean 
autoFormat,
+      @RequestParam(value = "maskedFieldNames", required = false) String 
maskedFieldNames)
       throws WorkSpaceException, IOException {
     ServletOutputStream outputStream = null;
     FsWriter fsWriter = null;
@@ -1169,7 +1183,30 @@ public class FsRestfulApi {
       if (isLimitDownloadSize) {
         fileSource = fileSource.page(1, excelDownloadSize);
       }
-      fileSource.write(fsWriter);
+      // 如果同时提供了字段屏蔽和字段截取参数,则先执行字段屏蔽,再执行字段截取
+      if (LinkisStorageConf.FIELD_MASKED_ENABLED()
+          && StringUtils.isNotBlank(maskedFieldNames)
+          && LinkisStorageConf.FIELD_TRUNCATION_ENABLED()) {
+        // 同时执行字段屏蔽和字段截取
+        StorageExcelWriter excelFsWriter = (StorageExcelWriter) fsWriter;
+        ResultUtils.applyFieldMaskingAndTruncation(
+            maskedFieldNames,
+            excelFsWriter,
+            fileSource,
+            LinkisStorageConf.FIELD_EXPORT_MAX_LENGTH());
+      } else if (LinkisStorageConf.FIELD_MASKED_ENABLED()
+          && StringUtils.isNotBlank(maskedFieldNames)) {
+        // 只执行字段屏蔽
+        ResultUtils.dealMaskedField(maskedFieldNames, fsWriter, fileSource);
+      } else if (LinkisStorageConf.FIELD_TRUNCATION_ENABLED()) {
+        // 只执行字段截取
+        StorageExcelWriter excelFsWriter = (StorageExcelWriter) fsWriter;
+        ResultUtils.detectAndHandle(
+            excelFsWriter, fileSource, 
LinkisStorageConf.FIELD_EXPORT_DOWNLOAD_LENGTH());
+      } else {
+        // Original stream write logic
+        fileSource.write(fsWriter);
+      }
       fsWriter.flush();
       LOGGER.info("userName {} Finished to resultsetsToExcel File {}", 
userName, path);
     } catch (Exception e) {


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to