效果

这个玩意的功能你们在这里自己看吧,我就不写了,对我的键盘友好一点吧(借口,其实懒得写)

代码

JS 代码

var selectedFile;  // 用于存储选择的文件
var encodeDecodeResult;  // 用于存储编码或解码的结果

function handleFileSelect(files) {
  if (files.length > 0) {
    selectedFile = files[0];
    displaySelectedFileName(selectedFile.name);
  }
}

function dropHandler(event) {
  event.preventDefault();
  handleFileSelect(event.dataTransfer.files);
}

function dragOverHandler(event) {
  event.preventDefault();
}

// 编码文本
function encodeText() {
  var inputText = document.getElementById("inputText").value;
  if (inputText) {
    var outputText = encodeUnicode(inputText);
    displayOutputText(outputText);
    displayResult("编码成功!");
  } else {
    displayResult("请输入文本!");
  }
}

// 辅助encodeText函数,让它使用UTF-8
function encodeUnicode(str) {
  // 将字符串转换为UTF-8,然后进行base64编码
  var utf8Bytes = new TextEncoder().encode(str);
  return btoa(String.fromCharCode.apply(null, utf8Bytes));
}

// 解码文本
function decodeText() {
  var inputText = document.getElementById("inputText").value;
  if (inputText) {
    try {
      var outputText = decodeUnicode(inputText); // 使用 decodeUnicode 替换 atob
      displayOutputText(outputText);
      displayResult("解码成功!");
    } catch (e) {
      displayResult("解码失败:" + e.message);
    }
  } else {
    displayResult("请输入文本!");
  }
}

// 辅助decodeText函数,使用UTF-8
function decodeUnicode(str) {
  // 对base64编码的字符串进行解码,然后转换为UTF-8字符串
  var bytes = atob(str).split('').map(function (char) {
    return char.charCodeAt(0);
  });
  return new TextDecoder().decode(new Uint8Array(bytes));
}

// 重置
function resetFields() {
  document.getElementById("inputText").value = "";
  document.getElementById("outputText").value = "";
  selectedFile = null;
  displaySelectedFileName("");
  displayResult("");
  encodeDecodeResult = null;
}

// 拷贝
function copyResult() {
  var outputText = document.getElementById("outputText");
  if (outputText.value) {
    outputText.select();
    document.execCommand("copy");
    displayResult("已复制到剪贴板!");
  } else {
    displayResult("没有可复制的内容!");
  }
}

// 编码文件
function encodeFile() {
  if (selectedFile) {
    var reader = new FileReader();
    reader.onload = function (event) {
      handleFileEncoding(event.target.result);
    };
    reader.readAsDataURL(selectedFile);
  } else {
    displayResult("请先选择文件!");
  }
}

// 辅助encodeFile函数
function handleFileEncoding(dataURL) {
  var sizeInBytes = calculateSizeInBytes(dataURL);
  var sizeInMB = sizeInBytes / (1024 * 1024);

  if (sizeInMB > 1) {
    displayResult('编码结果较大,请点击"下载结果"来保存');
  } else {
    displayOutputText(dataURL);
    displayResult('编码完成,请点击"复制"或"下载结果"进行保存');
  }

  encodeDecodeResult = dataURL;
}

function calculateSizeInBytes(dataURL) {
  return (dataURL.length * (3 / 4)) - (dataURL.endsWith("==") ? 2 : dataURL.endsWith("=") ? 1 : 0);
}

// 解码文件
function decodeFile() {
  // 检查是否有选择的文件
  if (selectedFile) {
    var reader = new FileReader();
    reader.onload = function (event) {
      try {
        handleFileDecoding(event.target.result);
      } catch (e) {
        displayResult("文件解码失败!错误信息: " + e.message);
      }
    };
    reader.readAsText(selectedFile);
  } else {
    // 如果没有选择的文件,尝试从输入框读取dataURL
    var inputText = document.getElementById("inputText").value;
    if (inputText) {
      try {
        handleFileDecoding(inputText);
      } catch (e) {
        displayResult("解码失败!错误信息: " + e.message);
      }
    } else {
      displayResult("请先选择文件或输入dataURL!");
    }
  }
}

// 辅助decodeFile
function handleFileDecoding(fileContent) {
  if (isDataURL(fileContent)) {
    var base64EncodedData = fileContent.split(',')[1];
    var mimeType = fileContent.split(',')[0].split(':')[1].split(';')[0];
    var byteArray = convertToByteArray(atob(base64EncodedData));
    encodeDecodeResult = new Blob([byteArray], { type: mimeType });
    displayResult("解码成功!请点击下载结果来保存");
  } else {
    displayResult("提供的内容不是有效的dataURL!");
  }
}

function isDataURL(str) {
  return str.startsWith('data:');
}

function convertToByteArray(decodedData) {
  var byteNumbers = new Array(decodedData.length);
  for (var i = 0; i < decodedData.length; i++) {
    byteNumbers[i] = decodedData.charCodeAt(i);
  }
  return new Uint8Array(byteNumbers);
}

function downloadResult() {
  if (encodeDecodeResult) {
    var blob = createBlobForDownload();
    initiateDownload(blob);
  } else {
    displayResult("没有可下载的内容!");
  }
}

function createBlobForDownload() {
  return encodeDecodeResult instanceof Blob ? encodeDecodeResult : new Blob([encodeDecodeResult], { type: "text/plain" });
}

function initiateDownload(blob) {
  var link = document.createElement("a");
  link.download = determineDownloadFileName(blob);
  link.href = URL.createObjectURL(blob);
  link.click();
  encodeDecodeResult = null;
}

function determineDownloadFileName(blob) {
  var fileName = "result";
  if (blob.type.startsWith("image/")) {
    fileName += "." + blob.type.split('/')[1];
  } else if (blob.type === "text/plain") {
    fileName += ".txt";
  }
  return fileName;
}

function displaySelectedFileName(fileName) {
  document.getElementById("selectedFile").innerHTML = fileName ? "已选择文件:" + fileName : "";
}

function displayOutputText(text) {
  document.getElementById("outputText").value = text;
}

function displayResult(message) {
  document.getElementById("result").innerHTML = message;
}

原理

没啥原理,就是利用了atobbtoa这俩函数,要是没这俩函数的话就没法做了

函数名

其中有一些没啥用的函数(显示状态、文件名;等等),真正有一些用处的函数就是atobbtoa这俩玩意了,不过我在这里只想讲讲这两个函数的命名.

首先,当我不知道这两玩意时,一直以为atobbtoa的 b 是 base64.

从上面的理解来看,atob是编码;btoa是解码,但是事实完全不同.

实际上,a指的是 ASCII 编码的字符串;而b指的是binary,即“二进制”;

而编码和解码的函数与我上面猜测的相反:atob是解码,btoa是编码.


为啥这样起函数名?

由于 base64 编码的发明初衷不像我们想象的那样,用来编码一句话,然后“加密”发给朋友(其实完全没有加密功能,“编码”和“加密”是【不同的】); 而是为了传输二进制数据的.

我们常见的很多文件都是使用“二进制”来存储的,比如:图片文件、压缩文件、音频和视频。

但是,这些二进制的文件很难通过网络传输,因为他们是二进制的;这是就需要 base64 登场了,它将二进制文件编码成一个dataURL,就变成了一个看得见、可编辑的字符串,这样就可以传输了.

至于dataURL是啥,可以看看知乎专栏的这篇文章,我认为讲的比较详细:戳这里

还有一篇 Mozilla 的文档:这里


完整源代码下载

这点玩意根本不入各位的法眼,放在GitHub就太丢人了,干脆直接在这里下载个zip么得了:

下载链接

不过,我的下载链接用的也是dataURL,哈哈哈哈哈哈


P.S.:很无聊,所以水一篇。但是我发现我连水一篇都懒的水 :(