簡體   English   中英

通過FormData上傳文件

[英]Uploading File via FormData

我正在嘗試將文件上傳到使用Multer的Node后端。 Multer要求以特定方式提交表單。 如果沒有以這種方式提交,則request.file參數將是undefined 我已經創建了一種使用蠻力的方法。 這種工作方法如下:

指數1.HTML:

<form method="POST" enctype="multipart/form-data" id="fileUploadForm">
  <input type="file" id="selectedFile" name="selectedFile" /><br/><br/>
  <input type="submit" value="Submit" id="btnSubmit"/>
</form>
...
var btn = document.getElementById('btnSubmit');
btn.addEventListener('click', function(e) {
  e.preventDefault();

  var form = $('#fileUploadForm')[0];
  var data = new FormData(form);
  console.log(data);

  $.ajax({
    type: "POST",
    enctype: 'multipart/form-data',
    url: "/upload",
    data: data,
    processData: false,
    contentType: false,
    cache: false,
    timeout: 600000,
    success: function (data) {
      console.log("SUCCESS!");
    },
    error: function (e) {
      console.log("ERROR : ", e);
    }
  });
});        

上面的代碼成功將文件發布到我的服務器。 該服務器具有以下內容:

server.js

app.post('/upload', upload.single('selectedFile'), function(req, res) {
  if (req.file) {
    console.log('file uploaded');
  } else {
    console.log('no file');
  }

  res.send({});
});

使用上面的代碼,“文件上傳”將按預期顯示在控制台窗口中。 但是,我需要一種更有活力的方法。 出於這個原因,我需要以編程方式在JavaScript中構建表單。 為了做到這一點,我創建了以下內容:

index-2.html [我的用戶界面]

var btn = document.getElementById('btnSubmit');
btn.addEventListener('click', function(e) {
  var form = document.createElement('form');
  form.action = '/upload';
  form.method = 'POST';
  form.enctype = 'multipart/form-data';

  var node = document.createElement("input");                        
  node.name = 'selectedFile';
  node.value = GLOBAL_SELECTED_FILE;
  form.appendChild(node);

  var data = new FormData(form);
  data.append('id', this.id);
  console.log(data);

  $.ajax({
    type: 'POST',
    url: '/profile-picture/upload',
    enctype: 'multipart/form-data',                          
    data: data,                            
    contentType: false,
    processData: false,
    success: function(res) {
      console.log('success!');
    },
    error: function(xhr, status, err) {
      console.log('error');
    }
  });
});

第二種方法不起作用。 為了澄清, GLOBAL_SELECTED_FILE變量是從輸入元素中選擇的文件的數據。 數據通過FileReader api加載。 看起來像這樣:

var GLOBAL_SELECTED_FILE = null;

var fileReader = new FileReader();      
fileReader.onload = function(e) {
  GLOBAL_SELECTED_FILE = e.target.result;
}
fileReader.readAsDataURL(fileSelected);  // file selected comes from the onchange event on a <input type="file">..</input> element

基本上,我正在加載圖像的預覽。 無論如何,當我點擊工作版本中的提交按鈕(index-1.html)時,我注意到在Fiddler中,對index-2.html中發送的值發送了不同的值。

使用index-1.html中的方法,Fiddler在“TextView”選項卡中顯示如下內容:

------WebKitFormBoundary183mBxXxf1HoE4Et
Content-Disposition: form-data; name="selectedFile"; filename="picture.PNG"
Content-Type: image/png

 PNG

但是,當我在Fiddler中查看通過index-2.html發送的數據的“TextView”選項卡時,我看到以下內容:

------WebKitFormBoundary9UHBP02of1OI5Zb6
Content-Disposition: form-data; name="selectedFile"

data:image/png;base64,iVBORw0KGg[A LOT MORE TO GO]

就像FormData對同一個值使用兩種不同的編碼一樣。 但是,我不明白為什么。 如何讓index-2.html以與index-1.html相同的格式發送圖像,以便Multer填充req.file屬性?

謝謝!

在index-1.html中,您正在使用文件輸入:

<input type="file" id="selectedFile" name="selectedFile" />

在index-2.html中,您正在創建普通表單輸入(不是文件輸入):

var node = document.createElement("input");                        
node.name = 'selectedFile';
node.value = GLOBAL_SELECTED_FILE;
form.appendChild(node);

要創建文件輸入,您需要添加node.type = 'file' 但是,您將無法設置該值,因為瀏覽器安全限制會阻止設置文件輸入的值。

相反,您需要做的是將用戶選擇的文件追加到FormData對象:

var data = new FormData(form);
data.append('id', this.id);
data.append('selectedFile', $('#fileInputElement')[0].files[0]);

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM