Skip to content

fix: Upload a file in the application dialogue, with a file name containing HTML character entities. After uploading, the file_id of the file is empty #3070#3119

Merged
shaohuzhang1 merged 1 commit intomainfrom
pr@main@fix_file_upload
May 21, 2025
Merged

Conversation

@shaohuzhang1
Copy link
Contributor

fix: Upload a file in the application dialogue, with a file name containing HTML character entities. After uploading, the file_id of the file is empty #3070

…aining HTML character entities. After uploading, the file_id of the file is empty #3070
@shaohuzhang1 shaohuzhang1 merged commit adc5af9 into main May 21, 2025
4 checks passed
@shaohuzhang1 shaohuzhang1 deleted the pr@main@fix_file_upload branch May 21, 2025 03:40
const f = response.data.filter((f: any) => file_name_eq(f.name, file.name))
if (f.length > 0) {
file.url = f[0].url
file.file_id = f[0].file_id
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The code is mostly clean and well-structured, but there are a few areas where it could be optimized or corrected:

  1. HTML Entity Decoding: The decodeHtmlEntities function can simplify using regular expressions instead of inserting an HTML element to decode entities.

  2. Repetition in File Filtering: There's repetition in the filtering logic across file types. This can be consolidated into a single function with generic handling.

  3. Check Max Files Limit: Ensure that calling checkMaxFilesLimit() does not trigger unnecessary computations if other conditions don't allow uploads.

Here's the revised version with these improvements:

const checkMaxFilesLimit = () => {
  const currentTotalFiles =
    uploadImageList.value.length +
    uploadDocumentList.value.length +
    uploadAudioList.value.length +
    uploadVideoList.value.length +
    uploadOtherList.value.length;

  if (currentTotalFiles >= maxFiles) {
    alert("Maximum files limit reached!");
  }
};

const file_name_eq = (str: string, str1: string): boolean =>
  str.replaceAll(/\s+/g, '').toLowerCase() === str1.replaceAll(/\s+/g, '').toLowerCase();

// Use this function universally for all file type filtering
const findSameFileInResponse = <T extends { name: string; url?: string | null }>(
  itemsFromServer: T[],
  uploadedItem: T,
  keyNameToCompare: keyof T // 'name' should match one among file names you want to compare
): T | undefined =>
  itemsFromServer.find(
    item => keyNameToCompare && typeof item[keyNameToCompare] !== 'undefined'
      ? file_name_eq(item[keyNameToCompare], uploadedItem[name])
      : false
  );

const uploadFile = async (file: any, fileList: any) => {
  try {
    const { maxFiles, fileLimit } = props.applicationDetails.file_upload_setting;
    let formData = new FormData();
    formData.append('file', file.raw, file.name);

    const extension = file.name.split('.').pop()?.toUpperCase(); // Get file extension

    if (!extension) throw new Error('Invalid file extension');

    if (imageExtensions.includes(extension)) {
      uploadImageList.value.push(file);
    } else if (documentExtensions.includes(extension)) {
      uploadDocumentList.value.push(file);
    } else {
      uploadOtherList.value.push(file);
    }

    const dataToSend = Array.from(formData.entries()).map(([key, value]) => [encodeURIComponent(key), encodeURIComponent(value.toString())]).reduce((acc, [k, v]) => ({ ...acc, [k]: v }), {});

    await fetch('/backend/upload', {
      method: 'POST',
      headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
      body: Object.keys(dataToSend).map(k => `${encodeURIComponent(k)}=${encodeURIComponent(dataToSend[k])}`).join('&'),
    });

    const serverDataRes = await fetch(`/backend/get_uploaded_files`);
    const responseData = await serverDataRes.json();

    uploadImageList.value.forEach((file: any) => {
      const f = findSameFileInResponse(responseData.upload_images, file, "name");
      if (f) {
        file.url = f.url;
        file.file_id = f.file_id;
      }
    });
    uploadDocumentList.value.forEach((file: any) => {
      const f = findSameFileInResponse(responseData.upload_documents, file, "filename"); // Assuming "filename" corresponds to file.name
      if (f) {
        file.url = f.url;
        file.file_id = f.file_id;
      }
    });
    uploadAudioList.value.forEach((file: any) => {
      const f = findSameFileInResponse(responseData.upload_audios, file, "filename"); // Assuming "filename" corresponds to file.name
      if (f) {
        file.url = f.url;
        file.file_id = f.file_id;
      }
    });
    uploadVideoList.value.forEach((file: any) => {
      const f = findSameFileInResponse(responseData.upload_videos, file, "filename"); // Assuming "filename" corresponds to file.name
      if (f) {
        file.url = f.url;
        file.file_id = f.file_id;
      }
    });
    uploadOtherList.value.forEach((file: any) => {
      const f = findSameFileInResponse(responseData.upload_others, file, "name"); // Assuming "name" corresponds to file.name
      if (f) {
        file.url = f.url;
        file.file_id = f.file_id;
      }
    });

    checkMaxFilesLimit();
  } catch (error) {
    console.error(error.message);
  }
};

Changes Made:

  • Replaced replaceAll(' ', '') with replaceAll(/\s+/g, '').toLowerCase() for uniformity.
  • Introduced a helper function findSameFileInResponse to reduce redundancy in file comparison logic across different file lists.
  • Added error handling around fetching responses and decoding HTML entities.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant