使用 FormData 和 multer 上传文件

2023-12-31

我已成功使用以下命令将文件上传到节点服务器multer通过使用输入文件对话框选择文件然后提交表单来模块,但现在我需要创建一个FormData对象,并使用发送文件XMLHttpRequest,但它不起作用,文件总是undefined在服务器端(路由器)。

执行 AJAX 请求的函数是:

function uploadFile(fileToUpload, url) {

  var form_data = new FormData();

  form_data.append('track', fileToUpload, fileToUpload.name);

  // This function simply creates an XMLHttpRequest object
  // Opens the connection and sends form_data
  doJSONRequest("POST", "/tracks/upload", null, form_data, function(d) {
    console.log(d);
  })

}

注意fileToUpload被定义并且url是正确的,因为调用了正确的路由器方法。fileToUpload is a File通过将文件从文件系统拖放到 dropzone,然后访问dataTransferdrop 事件的属性。

doJSONRequest是一个创建一个函数XMLHttpRequest对象并发送文件等(如评论中所述)。

function doJSONRequest(method, url, headers, data, callback){

  //all the arguments are mandatory
  if(arguments.length != 5) {
    throw new Error('Illegal argument count');
  }

  doRequestChecks(method, true, data);

  //create an ajax request
  var r = new XMLHttpRequest();

  //open a connection to the server using method on the url API
  r.open(method, url, true);

  //set the headers
  doRequestSetHeaders(r, method, headers);

  //wait for the response from the server
  r.onreadystatechange = function () {
    //correctly handle the errors based on the HTTP status returned by the called API
    if (r.readyState != 4 || (r.status != 200 && r.status != 201 && r.status != 204)){
      return;
    } else {
      if(isJSON(r.responseText))
        callback(JSON.parse(r.responseText));
      else if (callback !== null)
        callback();
    }
  };

  //set the data
  var dataToSend = null;
  if (!("undefined" == typeof data) 
    && !(data === null))
    dataToSend = JSON.stringify(data);

  //console.log(dataToSend)

  //send the request to the server
  r.send(dataToSend);
}

这是doRequestSetHeaders:

function doRequestSetHeaders(r, method, headers){

  //set the default JSON header according to the method parameter
  r.setRequestHeader("Accept", "application/json");

  if(method === "POST" || method === "PUT"){
    r.setRequestHeader("Content-Type", "application/json");
  }

  //set the additional headers
  if (!("undefined" == typeof headers) 
    && !(headers === null)){

    for(header in headers){
      //console.log("Set: " + header + ': '+ headers[header]);
      r.setRequestHeader(header, headers[header]);
    }

  }
}

我的路由器上传文件如下

// Code to manage upload of tracks
var multer = require('multer');
var uploadFolder = path.resolve(__dirname, "../../public/tracks_folder");

function validTrackFormat(trackMimeType) {
  // we could possibly accept other mimetypes...
  var mimetypes = ["audio/mp3"];
  return mimetypes.indexOf(trackMimeType) > -1;
}

function trackFileFilter(req, file, cb) {
  cb(null, validTrackFormat(file.mimetype));
}

var trackStorage = multer.diskStorage({
  // used to determine within which folder the uploaded files should be stored.
  destination: function(req, file, callback) {

    callback(null, uploadFolder);
  },

  filename: function(req, file, callback) {
    // req.body.name should contain the name of track
    callback(null, file.originalname);
  }
});

var upload = multer({
  storage: trackStorage,
  fileFilter: trackFileFilter
});


router.post('/upload', upload.single("track"), function(req, res) {
  console.log("Uploaded file: ", req.file); // Now it gives me undefined using Ajax!
  res.redirect("/"); // or /#trackuploader
});

我的猜测是multer不明白fileToUpload是一个带有名称的文件track(不是吗?),即中间件upload.single("track")无法正常工作/解析或什么都没有,或者可能根本无法与FormData,那样的话那就乱了。继续使用 multer 会有什么替代方案?

如何使用 AJAX 和 multer 上传文件?

如果您需要更多详细信息,请随时询问。


multer https://github.com/expressjs/multer uses multipart/form-data上传文件的内容类型请求。从你的doRequestSetHeaders函数应该可以解决你的问题:

if(method === "POST" || method === "PUT"){
   r.setRequestHeader("Content-Type", "application/json");
}

您不需要指定content-type since FormData对象已经使用正确的编码类型。来自docs https://developer.mozilla.org/en-US/docs/Web/API/FormData/Using_FormData_Objects:

传输的数据与表单的submit()格式相同 如果设置了表单的编码类型,则将使用该方法发送数据 到多部分/表单数据。

这是一个工作示例。它假设有一个带有 id 的 dropzonedrop-zone和一个 id 为的上传按钮upload-button:

var dropArea  = document.getElementById("drop-zone");
var uploadBtn = document.getElementById("upload-button");
var files     = [];

uploadBtn.disabled = true;
uploadBtn.addEventListener("click", onUploadClick, false);

dropArea.addEventListener("dragenter", prevent, false);
dropArea.addEventListener("dragover",  prevent, false);
dropArea.addEventListener("drop", onFilesDropped, false);   

//----------------------------------------------------
function prevent(e){

    e.stopPropagation();
    e.preventDefault();
}

//----------------------------------------------------
function onFilesDropped(e){

    prevent(e);

    files = e.dataTransfer.files;

    if (files.length){
        uploadBtn.disabled = false;
    }
}

//----------------------------------------------------
function onUploadClick(e){

    if (files.length){
        sendFile(files[0]);
    }
}

//----------------------------------------------------
function sendFile(file){

    var formData = new FormData();
    var xhr      = new XMLHttpRequest();

    formData.append("track", file, file.name);

    xhr.open("POST", "http://localhost:3000/tracks/upload", true);

    xhr.onreadystatechange = function () {  
        if (xhr.readyState === 4) {  
            if (xhr.status === 200) {  
                console.log(xhr.responseText);
            } else {  
                console.error(xhr.statusText);  
            }  
        }  
    };

    xhr.send(formData);
}

服务器端代码是一个简单的快速应用程序,其中包含您提供的确切路由器代码。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

使用 FormData 和 multer 上传文件 的相关文章

  • 使用 Android 发送 HTTP Post 请求

    我一直在尝试从 SO 和其他网站上的大量示例中学习 但我无法弄清楚为什么我编写的示例不起作用 我正在构建一个小型概念验证应用程序 它可以识别语音并将其 文本 作为 POST 请求发送到 node js 服务器 我已确认语音识别有效 并且服务
  • 如何在react-bootstrap中禁用表单提交的

    在下面的代码片段中 我有许多文本类型的输入表单 如果用户点击 我似乎会得到相同的合成事件 就像他们按下提交按钮一样 我想忽略作为表单提交 只允许一个人按下 提交 按钮 我删除了一些表单组以减少示例 在所有情况下 按钮或 ENTER 键 e
  • Chrome 中的性能问题

    我目前正在从事一个相对较大的项目 使用 AngularJs 构建 应用程序的一部分是一个表单 您可以向其中添加任意数量的页面 不幸的是 添加了很多不必要的垃圾 即表示表单模型的对象可能会变得非常大 在某些时候 Chrome 基本上无法处理它
  • 如何使用javascript将大图像转换为十六进制?

    如果我尝试将图像转换为十六进制 无论我使用哪个函数 我都会收到此错误消息 该图像的大小为 7 MB 19812 毫秒 清理 1401 2 1455 0 gt 1401 2 1455 0 MB 9 9 0 ms 自上次 GC 以来 8 3 m
  • 如何针对 Node.js 中发生的每个错误发送电子邮件?

    假设我的 node js 应用程序正在运行 如果出现错误 我的意思是所有错误 不仅仅是网络错误 如果出现错误 则很重要 我如何调用函数向我发送电子邮件 基本上 在我希望它写入 err out 之前 我希望向我发送一封电子邮件 我正在使用no
  • 使用 dc.js 按条形值对条形图中的条形进行排序(排序)

    如何通过维度的计算值而不是维度本身的名称对 dc js 示例中的 x 轴 维度 进行排序 例如 请考虑序数条形图的 dc js 示例 https github com dc js dc js blob master web examples
  • 将 GMT 时间转换为当地时间

    我以这种格式从我的服务器获取 GMT 时间 Fri 18 Oct 2013 11 38 23 GMT 我的要求是使用Javascript将此时间转换为本地时间 例如 如果用户来自印度 首先我需要采用时区 5 30并将其添加到我的服务器时间并
  • 如何制作没有 ng-repeat 的模板并使用 Angular-drag-and-drop-lists 将数据传递到 $scope?

    我想用角度拖放列表 https github com marceljuenemann angular drag and drop lists使用我自己的网格模板到所见即所得编辑器 如何构建我自己的 HTML 模板而不需要ng repeat因
  • window.location 和 location.href 之间的区别

    我对之间的区别感到困惑window location and location href 两者似乎都以相同的方式行事 有什么不同 window location是一个对象 它保存有关当前文档位置的所有信息 主机 href 端口 协议等 lo
  • 刷新页面时保存用户的选择

    我目前有一个页面显示不同团队的数据 我有一些数据 用户可以单击使其处于 打开 或 关闭 状态 并为每个数据显示不同的图标 它基本上就像一个清单 只是没有物理复选框 我想记住哪些 复选框 已被选中 即使在用户刷新页面或关闭浏览器并稍后返回之后
  • 为什么我们在打字稿中使用 HTMLInputElement ?

    我们为什么使用 document getElementById ipv as HTMLInputElement value 代替 document getElementById ipv value 功能getElementById返回具有类
  • DataTables row.add 到特定索引

    我正在替换这样的行项目 var targetRow entity row dataTable targetRow closest table dataTable DataTable dataTable row targetRow remov
  • 可以设置标题样式吗? (并且使用CSS或js?)[重复]

    这个问题在这里已经有答案了 我想知道是否可以设计一个title a href title This is a title Hello a 样式问题有两个方面 文本格式 编码 我猜这是可能的 所以在问题中这样做 工具提示样式 你能把它弄大一点
  • Javascript 假值(null、未定义、false、空字符串:“”或 '' 和 0)和比较(==)运算符 [重复]

    这个问题在这里已经有答案了 当我使用任何一个值时 null undefined false 0 in a if陈述 它总是被评估为谬误 false 另外 这些值的否定 null undefined false 0 in a if语句总是被评
  • 日期出现奇怪的错误,“未捕获非法访问”

    所以我试图找到最新的DateJavascript 可以处理 我把它减少到 9 月 275760 并增加了我开始捕获未捕获的天数illegal access例外new Date 09 24 275760 to new Date 10 13 2
  • 使用 Vue 的多模式组件

    我在 Vue 中实现动态模式组件时遇到问题 A common approach I follow to display a set of data fetched from the db is I dump each of the rows
  • 如何隐藏/禁用 Highcharts.js 中的图例框?

    我想问是否可以使用 HighCharts js 库隐藏图表中的所有图例框 var chart object chart renderTo render to type graph type colors graph colors title
  • 使用 postgres 和 node js 在单个语句中执行多个查询

    我需要在像这样的单个语句中执行插入和删除查询 INSERT INTO COMPANY ID NAME VALUES 1 Paul DELETE FROM COMPANY WHERE ID 12 这是我用于执行查询的 node js 代码 p
  • 使用 Mongoose 无法找到按 ObjectId 搜索的文档

    Campaign find client id req param client id error campaigns gt if error response error error message else for campaign i
  • 带参数的事件监听器

    我想将参数传递给 JavaScript 中的事件侦听器 我已经找到了解决方案 但我无法理解它们为什么或如何工作以及为什么其他解决方案不起作用 我有 C C 背景 但是 Javascript 函数的执行有很大不同 您能否帮助我理解以下示例如何

随机推荐

  • 将图标作为资源嵌入到 WPF 应用程序中

    我正在尝试将一个图标嵌入到我的 WPF 应用程序中 以便我可以使用以下代码将其拉出以用作 Windows 7 JumpList 中的图标 newScene IconResourcePath System Reflection Assembl
  • 不区分大小写的正则表达式

    在 Haskell 中使用带有选项 标志 的正则表达式的最佳方法是什么 I use Text Regex PCRE 该文档列出了一些有趣的选项 例如 compCaseless compUTF8 但我不知道如何使用它们 All the Tex
  • 如何使用 lodash 比较对象而不考虑其顺序

    我正在尝试使用 lodash 比较两个对象 如下所示 问题是它总是返回 false 我认为问题在于对象具有不同的键和值顺序 然而 无论订单如何 我都找不到如何比较它的解决方案 如何忽略顺序并正确比较两个对象 var obj1 event p
  • 是否可以更改 sendEmail 中的“发件人电子邮件”?

    我目前正在编写一个脚本 如果 Excel 已更新 该脚本会向用户发送电子邮件 我能够发送电子邮件 但是 在测试时 我注意到 发件人 电子邮件是我的电子邮件 我想将 发件人 电子邮件更改为另一个电子邮件 电子邮件受保护 cdn cgi l e
  • 如何在 k8s 集群中更新 Prometheus 配置

    我在 k8s 中运行 Prometheus 你能告诉我如何更改运行配置吗prometheus yaml在集群中 我只想简单地改变 scrape configs job name my exporter scrape interval 15s
  • Javascript:让用户选择像 Firebug 这样的 HTML 元素?

    我想编写一个浏览器 Chrome FF 扩展 需要选择网页上的元素 我希望它的行为像 Firebug 的元素检查器那样 单击检查箭头 然后可以悬停 突出显示元素 当您单击所需的元素时 系统会检查该元素 我只是对允许用户选择元素的代码感兴趣
  • jOOQ:在单个对象中返回带有 join、groupby 和 count 的列表

    核心问题 如何正确地将查询中的信息获取到对象中 Idea我正在 DAO 中创建函数 这可以归结为以下查询 select A count from A left join B on B aId A aId group by A 我正在寻找一种
  • RXTX gnu.io.PortInUseException:&警告:RXTX 版本不匹配

    我正在尝试使用 RXTX API 通过 Java Marine API 从 NMEA 0183 GPS 获取 GPS 数据 运行 Java Marine 提供的 SerialPortExample java 我返回两个错误 也许它们是相关的
  • Unity脚本执行顺序和Start()

    Unity的文档中有这样一行 默认情况下 不同脚本的Awake OnEnable和Update函数按照脚本加载的顺序 任意 被调用 所以我在这里有两个问题 在这种情况下 任意 是什么意思 是随机的吗 这是否还包括 Start 和 Awake
  • 如何在node.js中使用集群?

    我对 Node js 和 Express 非常陌生 我目前正在通过构建自己的服务来学习它 我最近读到了有关集群的内容 我明白了集群的作用 我无法理解的是如何在生产应用程序中使用集群 我能想到的一种方法是使用主进程坐在前面 并以循环方式将传入
  • 通过c++接口导出整个类

    好的 我会重写问题 1 做的够吗 class declspec dllexport CXyz public int Food printf Food n 这样该类就可以在 exe 中像这样使用 include CXyz h CXyz obj
  • Imageview 和 PagerAdapter

    我想将图像放在 ViewPager 的每个页面中 就像一本书 这些图像来自 url 列表 我的适配器看起来像这样 private class MyPagerAdapter extends PagerAdapter Override publ
  • 警告:基类“A”应该在复制构造函数中显式初始化

    我有以下类结构 class A A A const A src class B virtual A B A B const B src A src class C virtual A C A C const C src A src clas
  • 以编程方式访问 Servlet 3.0 中的 MultiPartConfig

    我使用Servlet 3 MultiPartConfig在我的应用程序中实现文件上传的注释 我需要在运行时设置多部分配置位置参数 而不是在注释参数中硬编码 是否有任何 API 可用于以编程方式访问 servlet 的多部分配置 Thanks
  • ASP.NET WebAPI - 如何使用 $.getJSON 传递对象

    我有一个 ASP NET WebAPI 控件如下 public SomeObject GetBenchMarkData Comment comment do stuff 在客户端 我正在尝试以下操作 var comment ID 0 Tex
  • 如何在OpenCV中用随机颜色绘制圆圈

    我正在使用 SURF 算法与 OpenCV 匹配两个图像 我已经掌握了关键点 现在我想用随机颜色的圆圈绘制这些关键点 我知道如何用函数 cvCircle 在 OpenCV 中画一个圆 但颜色是固定的cvScalar r g b 我希望图像中
  • 为什么 Ember.onerror() 没有捕获断言失败错误。?

    我的代码中有一种情况 我需要跟踪生产中的错误 I used ember js作为我的框架 为了跟踪我使用的生产中发生的错误Ember Onerror它只为我提供任何功能错误跟踪 Ember onerror function error Em
  • 如何让 Python 说话

    我怎样才能让 Python 说出一些文本 我可以将 Festival 与子进程一起使用 但我无法控制它 或者可能在交互模式下 但它不会是干净的 有Python TTS 库吗 比如 Festival eSpeak 的 API 您应该尝试使用
  • Jenkins+Github:我们无法交付此有效负载:无法连接到服务器

    我正在尝试在 GitHub 上配置 Web 挂钩 以便它可以将 POST 发送到http 127 0 0 1 8080 github webhook http 127 0 0 1 8080 github webhook 我的詹金斯正在运行h
  • 使用 FormData 和 multer 上传文件

    我已成功使用以下命令将文件上传到节点服务器multer通过使用输入文件对话框选择文件然后提交表单来模块 但现在我需要创建一个FormData对象 并使用发送文件XMLHttpRequest 但它不起作用 文件总是undefined在服务器端