Last active
September 23, 2023 23:45
-
-
Save RJHsiao/c3ae6925853505a7e2c11dc7dc14edce to your computer and use it in GitHub Desktop.
File-DataURL Converter
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!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