Skip to content

Instantly share code, notes, and snippets.

@RJHsiao
Last active September 23, 2023 23:45
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save RJHsiao/c3ae6925853505a7e2c11dc7dc14edce to your computer and use it in GitHub Desktop.
Save RJHsiao/c3ae6925853505a7e2c11dc7dc14edce to your computer and use it in GitHub Desktop.
File-DataURL Converter
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>File-DataURL Converter</title>
<style>
.converter-block > textarea {
width: 800px;
height: 300px;
}
</style>
</head>
<body>
<h1>File-DataURL Converter</h1>
<p>version: v1.0.1</p>
<a href="https://developer.mozilla.org/zh-TW/docs/Web/HTTP/Basics_of_HTTP/Data_URLs" target="_blank">What is DataURL?</a>
<hr>
<div id="file-to-data_url" class="converter-block">
<header>File → DataURL</header>
<input type="file" id="input-file" required>
<button id="convert-to-data_url">Convert</button>
<input type="checkbox" id="option-split-output" checked>
<label for="option-split-output">Split the output.</label>
<input type="checkbox" id="option-output-filename" checked>
<label for="option-output-filename">Add filename on the first line.</label>
<br>
<textarea id="output-data_url"></textarea>
</div>
<hr>
<div id="data_url-to-file" class="converter-block">
<header>DataURL → File</header>
<textarea id="input-data_url" required></textarea>
<br>
<label for="output-file-filename">Filename:</label>
<input type="text" id="output-file-filename" required>
<button id="convert-to-file">Convert</button>
<a id="output-file-downloader" style="display: none;">DataUrl download</a>
</div>
<script>
const inputFiles = document.getElementById('input-file');
const optionSplitOutput = document.getElementById('option-split-output')
const optionOutputFilename = document.getElementById('option-output-filename')
const outputDataURL = document.getElementById('output-data_url');
document.getElementById('convert-to-data_url').onclick = e => {
if (!inputFiles.reportValidity()) {
return;
}
outputDataURL.value = optionOutputFilename.checked ? inputFiles.files[0].name + '\n' : '';
const reader = new FileReader();
reader.readAsDataURL(inputFiles.files[0]);
reader.onload = e => {
const dataUrl = reader.result;
if (!optionSplitOutput.checked) {
outputDataURL.value += dataUrl;
return;
}
let begin = dataUrl.indexOf(',') + 1, lineCount = 0;
outputDataURL.value += dataUrl.slice(0, begin) + '\n';
while (begin < dataUrl.length) {
if (lineCount >= 900) {
outputDataURL.value += '\n';
lineCount = 0;
}
outputDataURL.value += dataUrl.slice(begin, begin + 100) + '\n';
begin += 100;
lineCount++;
}
}
}
const dataUrlRegExp = (() => {
const tokenChars = String.raw/* regexp */`\w-.~?#!$&'*+`;
const urlChars = String.raw/* regexp */`${tokenChars}:/\[\]@(),;=`;
const mimeType = (() => {
const mainType = String.raw/* regexp */`(?<mainType>[\w-]+)`;
const subType = String.raw/* regexp */`(?<subType>[\w-.]+)`;
const suffix = String.raw/* regexp */`(?<suffix>\w+)`;
const parameters = String.raw/* regexp */`(?<parameters>(;[${tokenChars}]+=[${tokenChars}]+)*)`;
return String.raw/* regexp */`(?<mimeType>${mainType}\/${subType}(\+${suffix})?(${parameters})?)`;
})();
const base64 = String.raw/* regexp */`(?<base64>;base64)`
const data = String.raw/* regexp */`(?<data>[${urlChars}]+)`
const fullRegexp = String.raw/* regexp */`^data:${mimeType}?${base64}?,${data}$`;
return new RegExp(fullRegexp, 'i')
})();
const inputDataURL = document.getElementById('input-data_url');
const outputFileFilename = document.getElementById('output-file-filename')
const outputFileDownloader = document.getElementById('output-file-downloader')
document.getElementById('convert-to-file').onclick = e => {
if (!inputDataURL.reportValidity() || !outputFileFilename.reportValidity()) {
return;
}
const dataUrl = inputDataURL.value.split('\n').map(str => str.trim()).join('');
const match = dataUrl.match(dataUrlRegExp)
if (!match) {
inputDataURL.setCustomValidity('Please input dataUrl!')
inputDataURL.reportValidity();
return;
}
const dataUrlObject = {
mimeType: {
value: match.groups.mimeType ?? 'text/plain;charset=US-ASCII',
mainType: match.groups.mainType ?? 'text',
subType: match.groups.subType ?? 'plain',
suffix: match.groups.suffix,
parameters: match.groups.mimeType
? match.groups.parameters
?.split(';')
?.filter(p => p.length)
?.map(p => {
let name, value;
[name, value] = p.split('=');
return {name, value};
})
: 'charset=US-ASCII',
},
isBase64: match.groups.base64 == true,
data: match.groups.data,
originalUrl: dataUrl,
};
console.log(dataUrlObject);
outputFileDownloader.href = dataUrl;
outputFileDownloader.download = outputFileFilename.value;
outputFileDownloader.click();
}
</script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment