如何在不跳过的情况下从Javascript页面获取多个文件上传到服务器?

磁通

我正在进行一项研究实验,该实验使用在Recorder.js中实现的getUserMedia来记录用户麦克风中的.wav文件和XMLHttpRequest并将其上传到服务器。每个文件大约3秒钟长,总共有36个文件。文件被一个接一个地记录,并在记录后立即发送到服务器。

我遇到的问题是,并非所有文件都最终存储在服务器上。显然,脚本或php脚本无法赶上连续的所有请求。如何确保我获得了所有文件?这些都是重要的研究数据,因此我需要每一个记录。

这是将文件发送到服务器的代码。音频数据是一个斑点:

var filename = subjectID + item__number;    
xhr.onload=function(e) {
    if(this.readyState === 4) {
    console.log("Server returned: ",e.target.responseText);
    }
};
var fd=new FormData();
fd.append("audio_data",blob, filename);
xhr.open("POST","upload_wav.php",true);
xhr.send(fd);

这是服务器端的php文件:

print_r($_FILES);     
$input = $_FILES['audio_data']['tmp_name'];
$output = "audio/".$_FILES['audio_data']['name'].".wav";
move_uploaded_file($input, $output)

这种处理方式基本上是从此网站复制的:使用Recorder.js捕获HTML5中的WAV音频并将其上传到您的服务器或本地下载

我已经尝试通过使用以下命令使XMLHttpRequest等待

   while (xhr.readyState != 4) 
   { 
     console.log("Waiting for server...")
   }

它只是导致页面挂起。

使用ajax比使用XMLHttp Request更好吗?有什么办法可以确保所有文件都被上传?我对Java语言还很陌生,因此赞赏代码示例。

兰迪·卡斯本

我不知道您的体系结构是什么样子,但是这里有一个潜在的解决方案可以解决您的问题。

该解决方案使用Web Worker API减轻文件上传到子流程的负担。这是通过该API工作程序接口完成的这种方法之所以有效,是因为没有争用主流程的单个线程的问题-网络工作者在自己的流程中工作。

使用这种方法,我们做三件事:

  1. 创建一个通过脚本执行的新工作程序
  2. 将消息传递给工人,以便工人处理
  3. 将消息传递回主过程,以进行状态更新/回复/已解决的数据转换/等。

该代码在下面进行了大量注释,以帮助您了解正在发生的事情和发生的地方。

这是主要的JavaScript文件(script.js)

// Create a sub process to handle the file uploads
///// STEP 1: create a worker and execute the worker.js file immediately
let worker = new Worker('worker.js');
// Ficticious upload count for demonstration
let uploadCount = 12;
// repeatedly build and send files every 700ms 
// This is repeated until uplaodCount == 0
let builder = setInterval(buildDetails, 700);

// Recieve message from the sub-process and pipe them to the view
///// STEP 2: listen for messages from the worker and do something with them
worker.onmessage = e => {
  let p = document.createElement('pre');
  // e.data represents the message data sent from the sub-process
  p.innerText = e.data;
  document.body.appendChild(p);
};

/**
 * Sort of a mock to build up your BLOB (fake here of-course)
 * 
 * Post the data needed for the FormData() to the worker to handle.
 */ 
function buildDetails() {
  let filename = 'subject1234';
  let blob = new Blob(['1234']);
  ///// STEP 3: Send a message to the worker with file details
  worker.postMessage({
    name: "audio_data",
    blob: blob,
    filename: filename
  });
  // Decrease the count
  uploadCount--;
  // if count is zero (== false) stop the fake process
  if (!uploadCount) clearInterval(builder);
}

这是子流程JavaScript文件(worker.js)

// IGNORE the 'fetch_mock.js' import that is only here to avoid having to stand up a server
// FormDataPolyFill.js is needed in browsers that don't yet support FormData() in workers
importScripts('FormDataPolyFill.js', 'fetch_mock.js');
// RXJS provides a full suite of asynchronous capabilities based around Reactive Programming (nothing to do with ReactJS);
// The need for your use case is that there are guarantees that the stream of inputs will all be processed
importScripts('https://cdnjs.cloudflare.com/ajax/libs/rxjs/6.3.3/rxjs.umd.js');

// We create a "Subject" that acts as a vessel for our files to upload
let forms = new rxjs.Subject();
// This says "every time the forms Subject is updated, run the postfile function and send the next item from the stream"
forms.subscribe(postFile);

// Listen for messages from the main process and run doIt each time a message is recieved
onmessage = doIt;

/**
 * Takes an event object containing the message
 * 
 * The message is presumably the file details
 */ 
function doIt(e) {
  var fd = new FormData();
  // e.data represents our details object with three properties
  fd.append(e.data.name, e.data.blob, e.data.filename);
  // Now, place this FormData object into our stream of them so it can be processed
  forms.next(fd);
}
// Instead of using XHR, this uses the newer fetch() API based upon Promises
// https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API
function postFile(fd) {
  // Post the file to the server (This is blocked in fetch_mock.js and doesn't go anywhere)
  fetch('fake', {
      method: 'post',
      body: fd,
    })
    .then((fd) => {
      // After the XHR request is complete, 'Then' post a message back to the main thread (If there is a need);
      postMessage("sent: " + JSON.stringify(fd));
    });
}

由于这不会在stackoverflow中运行,因此我创建了一个插件,以便您可以运行以下示例:http ://plnkr.co/edit/kFY6gcYq627PZOATXOnk

如果这一切看起来都很复杂,那么您已经提出了要解决的复杂问题。:-)

希望这可以帮助。

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章

如何在不将数据上传到服务器的情况下使用 Devextreme Angular 文件上传器

如何在没有浏览器的情况下使用go将文件上传到服务器?

如何在不使用C#浏览的情况下将文件从系统中的已知路径上传到Web服务器

如何在不跳过的情况下获取 scan.nextLine()

在没有服务器的情况下测试Ruby Rack时如何伪造文件上传?

如何在将文件上传到服务器之前验证用户发送的文件?- Javascript

如何在不重启服务器的情况下编译单个/多个Java文件?是否有相同的Eclipse插件?

如何在不触发页面刷新的情况下将数据提交到服务器?

如何在不使用表单的情况下向服务器提交来自 JavaScript 的获取请求

如何在不使用 libcurl 的情况下从本地主机服务器获取 URL

如何在不使用系统时间的情况下从服务器获取时间

如何在没有AWS JavaScript SDK的情况下将文件上传到S3?

如何在不跳过列的情况下从“合并”单元格复制和粘贴公式

如何在不跳过行的情况下写入从json转换为csv的数据

如何在不跳过的情况下读取 Java 中的整行输入(scanner.next())

如何在不覆盖用户文件的情况下更新生产服务器?

如何在不重新启动服务器的情况下更改Javascript?

如何在禁用JavaScript的情况下运行SPA-服务器端渲染?

如何在不使用 Google Drive 的情况下从 Github 将文件上传到 Colab?

将单个文件上传到多个服务器

在我的代码中不使用FTP信息的情况下将图像上传到服务器?

在不使用Express的情况下将图像上传到Node.js中的服务器

如何在 Ubuntu 服务器之间传输文件,以便 A 使用密钥登录到 B 并在不登录到 A 的情况下获取文件?

如何在不使用javascript更改页面的情况下访问文件上传所选文件?

如何使用ajax+jquery将多个文件上传到服务器?

如何使用php将多个文件上传到000webhost服务器?

如何使用UnityWebRequest.Post()将多个文件上传到服务器

在没有 PHP 服务器的情况下从 Arduino 直接上传到 SQL 服务器有哪些安全风险?

使用php将多个文件上传到服务器,而不将所有文件上传到服务器