feat(base64 file converter): add a filename and extension fields
Add filename and extension (auto filled if data url) to allow downloading with right extension and filename Fix #788
This commit is contained in:
		
							parent
							
								
									3e27051f8f
								
							
						
					
					
						commit
						435d81281b
					
				@ -1,8 +1,12 @@
 | 
				
			|||||||
import { extension as getExtensionFromMime } from 'mime-types';
 | 
					import { extension as getExtensionFromMimeType, extension as getMimeTypeFromExtension } from 'mime-types';
 | 
				
			||||||
import type { Ref } from 'vue';
 | 
					import type { Ref } from 'vue';
 | 
				
			||||||
import _ from 'lodash';
 | 
					import _ from 'lodash';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export { getMimeTypeFromBase64, useDownloadFileFromBase64 };
 | 
					export {
 | 
				
			||||||
 | 
					  getMimeTypeFromBase64,
 | 
				
			||||||
 | 
					  getMimeTypeFromExtension, getExtensionFromMimeType,
 | 
				
			||||||
 | 
					  useDownloadFileFromBase64, useDownloadFileFromBase64Refs,
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const commonMimeTypesSignatures = {
 | 
					const commonMimeTypesSignatures = {
 | 
				
			||||||
  'JVBERi0': 'application/pdf',
 | 
					  'JVBERi0': 'application/pdf',
 | 
				
			||||||
@ -36,30 +40,55 @@ function getFileExtensionFromMimeType({
 | 
				
			|||||||
  defaultExtension?: string
 | 
					  defaultExtension?: string
 | 
				
			||||||
}) {
 | 
					}) {
 | 
				
			||||||
  if (mimeType) {
 | 
					  if (mimeType) {
 | 
				
			||||||
    return getExtensionFromMime(mimeType) ?? defaultExtension;
 | 
					    return getExtensionFromMimeType(mimeType) ?? defaultExtension;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  return defaultExtension;
 | 
					  return defaultExtension;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
function useDownloadFileFromBase64({ source, filename }: { source: Ref<string>; filename?: string }) {
 | 
					function downloadFromBase64({ sourceValue, filename, extension, fileMimeType }:
 | 
				
			||||||
 | 
					{ sourceValue: string; filename?: string; extension?: string; fileMimeType?: string }) {
 | 
				
			||||||
 | 
					  if (sourceValue === '') {
 | 
				
			||||||
 | 
					    throw new Error('Base64 string is empty');
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  const defaultExtension = extension ?? 'txt';
 | 
				
			||||||
 | 
					  const { mimeType } = getMimeTypeFromBase64({ base64String: sourceValue });
 | 
				
			||||||
 | 
					  let base64String = sourceValue;
 | 
				
			||||||
 | 
					  if (!mimeType) {
 | 
				
			||||||
 | 
					    const targetMimeType = fileMimeType ?? getMimeTypeFromExtension(defaultExtension);
 | 
				
			||||||
 | 
					    base64String = `data:${targetMimeType};base64,${sourceValue}`;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  const cleanExtension = extension ?? getFileExtensionFromMimeType(
 | 
				
			||||||
 | 
					    { mimeType, defaultExtension });
 | 
				
			||||||
 | 
					  let cleanFileName = filename ?? `file.${cleanExtension}`;
 | 
				
			||||||
 | 
					  if (extension && !cleanFileName.endsWith(`.${extension}`)) {
 | 
				
			||||||
 | 
					    cleanFileName = `${cleanFileName}.${cleanExtension}`;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  const a = document.createElement('a');
 | 
				
			||||||
 | 
					  a.href = base64String;
 | 
				
			||||||
 | 
					  a.download = cleanFileName;
 | 
				
			||||||
 | 
					  a.click();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					function useDownloadFileFromBase64(
 | 
				
			||||||
 | 
					  { source, filename, extension, fileMimeType }:
 | 
				
			||||||
 | 
					  { source: Ref<string>; filename?: string; extension?: string; fileMimeType?: string }) {
 | 
				
			||||||
  return {
 | 
					  return {
 | 
				
			||||||
    download() {
 | 
					    download() {
 | 
				
			||||||
      if (source.value === '') {
 | 
					      downloadFromBase64({ sourceValue: source.value, filename, extension, fileMimeType });
 | 
				
			||||||
        throw new Error('Base64 string is empty');
 | 
					    },
 | 
				
			||||||
      }
 | 
					  };
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
      const { mimeType } = getMimeTypeFromBase64({ base64String: source.value });
 | 
					
 | 
				
			||||||
      const base64String = mimeType
 | 
					function useDownloadFileFromBase64Refs(
 | 
				
			||||||
        ? source.value
 | 
					  { source, filename, extension }:
 | 
				
			||||||
        : `data:text/plain;base64,${source.value}`;
 | 
					  { source: Ref<string>; filename?: Ref<string>; extension?: Ref<string> }) {
 | 
				
			||||||
 | 
					  return {
 | 
				
			||||||
      const cleanFileName = filename ?? `file.${getFileExtensionFromMimeType({ mimeType })}`;
 | 
					    download() {
 | 
				
			||||||
 | 
					      downloadFromBase64({ sourceValue: source.value, filename: filename?.value, extension: extension?.value });
 | 
				
			||||||
      const a = document.createElement('a');
 | 
					 | 
				
			||||||
      a.href = base64String;
 | 
					 | 
				
			||||||
      a.download = cleanFileName;
 | 
					 | 
				
			||||||
      a.click();
 | 
					 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
  };
 | 
					  };
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -2,12 +2,19 @@
 | 
				
			|||||||
import { useBase64 } from '@vueuse/core';
 | 
					import { useBase64 } from '@vueuse/core';
 | 
				
			||||||
import type { Ref } from 'vue';
 | 
					import type { Ref } from 'vue';
 | 
				
			||||||
import { useCopy } from '@/composable/copy';
 | 
					import { useCopy } from '@/composable/copy';
 | 
				
			||||||
import { useDownloadFileFromBase64 } from '@/composable/downloadBase64';
 | 
					import { getExtensionFromMimeType, getMimeTypeFromBase64, useDownloadFileFromBase64Refs } from '@/composable/downloadBase64';
 | 
				
			||||||
import { useValidation } from '@/composable/validation';
 | 
					import { useValidation } from '@/composable/validation';
 | 
				
			||||||
import { isValidBase64 } from '@/utils/base64';
 | 
					import { isValidBase64 } from '@/utils/base64';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const fileName = ref('file');
 | 
				
			||||||
 | 
					const fileExtension = ref('');
 | 
				
			||||||
const base64Input = ref('');
 | 
					const base64Input = ref('');
 | 
				
			||||||
const { download } = useDownloadFileFromBase64({ source: base64Input });
 | 
					const { download } = useDownloadFileFromBase64Refs(
 | 
				
			||||||
 | 
					  {
 | 
				
			||||||
 | 
					    source: base64Input,
 | 
				
			||||||
 | 
					    filename: fileName,
 | 
				
			||||||
 | 
					    extension: fileExtension,
 | 
				
			||||||
 | 
					  });
 | 
				
			||||||
const base64InputValidation = useValidation({
 | 
					const base64InputValidation = useValidation({
 | 
				
			||||||
  source: base64Input,
 | 
					  source: base64Input,
 | 
				
			||||||
  rules: [
 | 
					  rules: [
 | 
				
			||||||
@ -18,6 +25,16 @@ const base64InputValidation = useValidation({
 | 
				
			|||||||
  ],
 | 
					  ],
 | 
				
			||||||
});
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					watch(
 | 
				
			||||||
 | 
					  base64Input,
 | 
				
			||||||
 | 
					  (newValue, _) => {
 | 
				
			||||||
 | 
					    const { mimeType } = getMimeTypeFromBase64({ base64String: newValue });
 | 
				
			||||||
 | 
					    if (mimeType) {
 | 
				
			||||||
 | 
					      fileExtension.value = getExtensionFromMimeType(mimeType) || fileExtension.value;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
 | 
					);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
function downloadFile() {
 | 
					function downloadFile() {
 | 
				
			||||||
  if (!base64InputValidation.isValid) {
 | 
					  if (!base64InputValidation.isValid) {
 | 
				
			||||||
    return;
 | 
					    return;
 | 
				
			||||||
@ -44,6 +61,24 @@ async function onUpload(file: File) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
<template>
 | 
					<template>
 | 
				
			||||||
  <c-card title="Base64 to file">
 | 
					  <c-card title="Base64 to file">
 | 
				
			||||||
 | 
					    <n-grid cols="3" x-gap="12">
 | 
				
			||||||
 | 
					      <n-gi span="2">
 | 
				
			||||||
 | 
					        <c-input-text
 | 
				
			||||||
 | 
					          v-model:value="fileName"
 | 
				
			||||||
 | 
					          label="File Name"
 | 
				
			||||||
 | 
					          placeholder="Download filename"
 | 
				
			||||||
 | 
					          mb-2
 | 
				
			||||||
 | 
					        />
 | 
				
			||||||
 | 
					      </n-gi>
 | 
				
			||||||
 | 
					      <n-gi>
 | 
				
			||||||
 | 
					        <c-input-text
 | 
				
			||||||
 | 
					          v-model:value="fileExtension"
 | 
				
			||||||
 | 
					          label="Extension"
 | 
				
			||||||
 | 
					          placeholder="Extension"
 | 
				
			||||||
 | 
					          mb-2
 | 
				
			||||||
 | 
					        />
 | 
				
			||||||
 | 
					      </n-gi>
 | 
				
			||||||
 | 
					    </n-grid>
 | 
				
			||||||
    <c-input-text
 | 
					    <c-input-text
 | 
				
			||||||
      v-model:value="base64Input"
 | 
					      v-model:value="base64Input"
 | 
				
			||||||
      multiline
 | 
					      multiline
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
		Reference in New Issue
	
	Block a user