html 在Javascript中同步读取文件

e4yzc0pl  于 2022-12-02  发布在  Java
关注(0)|答案(7)|浏览(277)

我想读取一个文件,并使用FileReader对象将其转换为base64编码字符串。下面是我使用的代码:

var reader = new FileReader();
    reader.onloadend = function(evt) {  
        // file is loaded
        result_base64 = evt.target.result; 
    };
    reader.readAsDataURL(file);

但在本例中,我在事件处理程序(onLoadEnd事件)中获得了转换的结果。我希望使用同步方法。是否有一种方法可以让“readAsDataURL”方法直接返回'result_base64'变量的值?

zour9fqk

zour9fqk1#

在Node.js中,使用child_process中的execSync,并让shell为您同步读入它。将此子进程的输出重定向到父进程。

// Don't forget to use your favorite encoding in toString()
var execSync = require('child_process').execSync;
var fileContents = execSync('cat path/to/file.txt', {stdio: "pipe"}).toString();

我很高兴接受你对UUOC奖的提名。)

bwitn5fc

bwitn5fc2#

您可以使用标准的FileReaderSync,它是FileReader API的一个更简单、同步、阻塞的版本,类似于您已经在使用的版本:

let reader = new FileReaderSync();
let result_base64 = reader.readAsDataURL(file); 

console.log(result_base64); // aGV5IHRoZXJl...

请记住,由于显而易见的原因,这只在工作线程中可用
如果你需要一个主线程的解决方案,它“读起来像”一个同步API,也就是顺序的,你可以把异步FileReader Package 在一个promise中,并使用异步函数(你可能需要transpile):

async function readFileAsDataURL(file) {
    let result_base64 = await new Promise((resolve) => {
        let fileReader = new FileReader();
        fileReader.onload = (e) => resolve(fileReader.result);
        fileReader.readAsDataURL(file);
    });

    console.log(result_base64); // aGV5IHRoZXJl...

    return result_base64;
}

然后,您可以在另一个异步上下文中等待该函数:

async function main() {
    let file = new File(...)
    let dataURL = await readFileAsDataURL(file)
    console.log(dataURL); // aGV5IHRoZXJl...
}

...或者只是使用约定回调来使用它(不需要异步上下文):

readFileAsDataURL(file).then(dataURL => {
    console.log(dataURL); // aGV5IHRoZXJl...
});
dfuffjeb

dfuffjeb3#

同步任务(阻塞)通常是不好的。如果没有真实的的理由同步地做那件事,我强烈建议你使用事件回调。
假设你的文件坏了,HTML5 api无法读取,它不会给予你结果。它会破坏你的代码并阻止网站。或者,有人可能选择了一个10GB的文件,这会冻结你的HTML页面,直到文件完全加载。通过异步事件处理程序,你可以捕捉可能的错误。
为了解决回调的限制,我使用了一个简单的技巧:

var ready = false;
var result = '';

var check = function() {
    if (ready === true) {
         // do what you want with the result variable
         return;
    }
    setTimeout(check, 1000);
}

check();

var reader = new FileReader();
reader.onloadend = function(evt) {
    // file is loaded
    result = evt.target.result;
    
    ready = true;
};
reader.readAsDataURL(file);

检查函数,每秒钟检查一次就绪标志变量是否被设置为真。2如果是,你可以确定结果是可用的。
这样做可能不是最好的做法,但我使用这种技术制作了一个Web应用程序,大约30次,同时运行10多个setTimeouts,直到现在都没有遇到任何问题。

wkyowqbh

wkyowqbh4#

截至2022年11月1日,file.getAsDataURL()已经过时,这是唯一的直接同步方法,只需将File对象传递给下面的函数,该函数将返回一个数据url。

readSyncDataURL=function(file){
var url=URL.createObjectURL(file);//Create Object URL
var xhr=new XMLHttpRequest();
xhr.open("GET",url,false);//Synchronous XMLHttpRequest on Object URL
xhr.overrideMimeType("text/plain; charset=x-user-defined");//Override MIME Type to prevent UTF-8 related errors
xhr.send();
URL.revokeObjectURL(url);
var returnText="";
for (var i=0;i<xhr.responseText.length;i++){
returnText+=String.fromCharCode(xhr.responseText.charCodeAt(i)&0xff);};//remove higher byte
return "data:"+file.type+";base64,"+btoa(returnText);}//Generate data URL

下一个函数只是一个将File对象转换为二进制字符串的通用函数(以防有人在搜索它):

readSyncBinaryString=function(file){
var url=URL.createObjectURL(file);//Create Object URL
var xhr=new XMLHttpRequest();
xhr.open("GET",url,false);//Synchronous XMLHttpRequest on Object URL
xhr.overrideMimeType("text/plain; charset=x-user-defined");//Override MIME Type to prevent UTF-8 related errors
xhr.send();
URL.revokeObjectURL(url);
var returnText="";
for (var i=0;i<xhr.responseText.length;i++){
returnText+=String.fromCharCode(xhr.responseText.charCodeAt(i)&0xff);};//remove higher byte
return returnText;}

如果需要ArrayBuffer,请使用此函数:

readSyncArrayBuffer=function(file){
var url=URL.createObjectURL(file);
var xhr=new XMLHttpRequest();
xhr.open("GET",url,false);//Synchronous XMLHttpRequest on Object URL
xhr.overrideMimeType("text/plain; charset=x-user-defined");//Override MIME Type to prevent UTF-8 related errors
xhr.send();
URL.revokeObjectURL(url);
var returnArray=[];
for (var i=0;i<xhr.responseText.length;i++){
returnArray.push(String.fromCharCode(xhr.responseText.charCodeAt(i)&0xff));};//remove higher byte
return new Uint8Array(returnArray).buffer;}//Generate Buffer
vaj7vani

vaj7vani5#

下面的代码以同步方式读取文件

function SyncFileReader(file) {
    let self = this;
    let ready = false;
    let result = '';

    const sleep = function (ms) {
      return new Promise(resolve => setTimeout(resolve, ms));
    }

    self.readAsArrayBuffer = async function() {
        while (ready === false) {
          await sleep(100);
        }
        return result;
    }    

    const reader = new FileReader();
    reader.onloadend = function(evt) {
        result = evt.target.result;
        ready = true;
    };
    reader.readAsArrayBuffer(file);
  }

用法:

const fileReader = new SyncFileReader(file);
const arrayBuffer = await fileReader.readAsArrayBuffer();
thtygnil

thtygnil6#

要同步读取文件的内容,请使用fs.readFileSync

var fs = require('fs');
var content = fs.readFileSync('myfilename');
console.log(content);

创建一个读取流。

z9gpfhce

z9gpfhce7#

下面的代码以同步方式读取文件并以文本(字符串)形式返回其内容

function SyncFileReader(file) {
    let self = this;
    let ready = false;
    let result = '';

    const sleep = function (ms) {
      return new Promise(resolve => setTimeout(resolve, ms));
    }

    self.readAsDataURL = async function() {
        while (ready === false) {
          await sleep(100);
        }
        return result;
    }    

    const reader = new FileReader();
    reader.onloadend = function(evt) {
        result = evt.target.result;
        ready = true;
    };
    reader.readAsDataURL(file);
  }

用法:

const fileReader = new SyncFileReader(file);
const arrayBuffer = await fileReader.readAsDataURL();

相关问题