上传文件无需表单

119

不使用任何表单,我能否仅使用jQuery将文件/文件从 <input type="file"> 发送到 'upload.php' 并使用 POST 方法。输入标签不在任何表单标签内。它是独立的。因此,我不想使用 jQuery 插件如 'ajaxForm' 或 'ajaxSubmit'。


2
嗯...我想说它应该在HTML 5中工作。但是会存在平台兼容性问题和早于几年的浏览器。创建一个表单或从底层动态生成一个表单有什么坏处呢? - Yitzhak
7个回答

114

您可以使用FormData通过POST请求提交数据。以下是一个简单的示例:

var myFormData = new FormData();
myFormData.append('pictureFile', pictureInput.files[0]);

$.ajax({
  url: 'upload.php',
  type: 'POST',
  processData: false, // important
  contentType: false, // important
  dataType : 'json',
  data: myFormData
});

只要您知道请求设置(如url、method和参数数据),就不必使用表单进行ajax请求。


8
别忘了在设置对象中加入 processData: falsecontentType: false,否则你将收到 Uncaught TypeError: Illegal invocation 错误。 - jsmiff
2
大佬们,你们救了我的命!!:D 感谢 @monshi 和 @jsmiff。(SOF不允许在同一条评论中提及多个用户) - Silvio Delgado
5
这里的pictureInput是什么意思? - SAUMYA
1
@developersaumya pictureinput 是文件输入的 DOM 元素。 - Omid Monshizadeh
如果您计划像示例中那样使用PHP接收请求,请参考Hadiyal Rakesh的答案以了解如何检索FormData的内容。对于专家而言,它被发送为“multipart/form-data”。 - Arnaud
显示剩余2条评论

51
这里的所有答案仍在使用FormData API。它类似于没有表单的"multipart/form-data"上传。您还可以像这样在POST请求的正文中直接上传文件内容,使用xmlHttpRequest
var xmlHttpRequest = new XMLHttpRequest();

var file = ...file handle...
var fileName = ...file name...
var target = ...target...
var mimeType = ...mime type...

xmlHttpRequest.open('POST', target, true);
xmlHttpRequest.setRequestHeader('Content-Type', mimeType);
xmlHttpRequest.setRequestHeader('Content-Disposition', 'attachment; filename="' + fileName + '"');
xmlHttpRequest.send(file);

Content-TypeContent-Disposition头用于解释我们正在发送的内容(媒体类型和文件名)。

我也在这里发布了类似的答案。

更新(January 2023):

您还可以使用Fetch API直接上传二进制内容的文件(正如评论中建议的那样)。

const file = ...file handle...
const fileName = ...file name...
const target = ...target...
const mimeType = ...mime type...

const promise = fetch(target, { 
  method: 'POST', 
  body: file, 
  headers: {
    'Content-Type': mimeType,
    'Content-Disposition': `attachment; filename="${fileName}"`,
  },
});

promise.then(
  (response) => { /*...do something with response*/ },
  (error) => { /*...handle error*/ },
);

请参阅此相关问题:https://dev59.com/HFYM5IYBdhLWcg3wvCD-#48568899


1
这是一个很好的答案。它完全避免了表单数据的使用。我可以补充一下关于xmlHttpRequest的用法。XMLHttpRequest允许执行异步操作,不会阻塞客户端(UI页面)。而在使用HTML表单时,客户端(UI页面)在操作执行期间会被阻塞。 - Harry
1
fetch() 怎么样? - Vitaly Zdanevich
2
@VitalyZdanevich,你的意思是什么? - Wilt
1
@ar2015 不确定你的意思是什么?但是后端不关心你使用选项一还是选项二。从后端的角度来看,它们完全相同。或者你是指如何在后端支持二进制上传? - Wilt
1
@AlessandroLendaro 感谢您的评论,我已经相应地更新了答案... - Wilt
显示剩余3条评论

18

步骤1:创建HTML页面,用于放置HTML代码。

步骤2:在HTML代码页面底部(页脚)创建Javascript:<script>,并在Script标签中放置Jquery代码。

步骤3:创建PHP文件,并将php代码复制粘贴。在$.ajax代码中的url应用您的php文件名称。

JS

//$(document).on("change", "#avatar", function() {   // If you want to upload without a submit button 
$(document).on("click", "#upload", function() {
  var file_data = $("#avatar").prop("files")[0]; // Getting the properties of file from file field
  var form_data = new FormData(); // Creating object of FormData class
  form_data.append("file", file_data) // Appending parameter named file with properties of file_field to form_data
  form_data.append("user_id", 123) // Adding extra parameters to form_data
  $.ajax({
    url: "/upload_avatar", // Upload Script
    dataType: 'script',
    cache: false,
    contentType: false,
    processData: false,
    data: form_data, // Setting the data attribute of ajax with file_data
    type: 'post',
    success: function(data) {
      // Do something after Ajax completes 
    }
  });
});

HTML

<input id="avatar" type="file" name="avatar" />
<button id="upload" value="Upload" />

Php

->

Php

print_r($_FILES);
print_r($_POST);

1
请为您的代码添加一些注释/描述。 - kvorobiev
1
让我开心了 :) 谢谢 - shekhardtu
我该如何在 Java 代码中引用这些表单变量? - Bhaskara Arani
我不知道为什么,但当我加上 "dataType: 'script'" 时,出现了一个错误。只需要删除这部分内容,它就可以完美地工作了。谢谢。 - Majid Qafouri
Php 部分只有两行,但非常珍贵,谢谢! - Arnaud
显示剩余5条评论

14

根据[这个教程][1],以下是一个非常基本的方法:

$('your_trigger_element_selector').on('click', function(){    
    var data = new FormData();
    data.append('input_file_name', $('your_file_input_selector').prop('files')[0]);
    // append other variables to data if you want: data.append('field_name_x', field_value_x);
    
    $.ajax({
        type: 'POST',               
        processData: false, // important
        contentType: false, // important
        data: data,
        url: your_ajax_path,
        dataType : 'json',  
        // in PHP you can call and process a file in the same way as if it was submitted in a form:
        // $_FILES['input_file_name']
        success: function(jsonData){
            ...
        }
        ...
    }); 
});

不要忘记添加适当的错误处理 [1]: http://abandon.ie/notebook/simple-file-uploads-using-jquery-ajax


3
一个非 jQuery (React) 版本: JS:
function fileInputUpload(e){

    let formData = new FormData();
    formData.append(e.target.name, e.target.files[0]);

    let response = await fetch('/api/upload', {
      method: 'POST',
      body: formData
    });

    let result = await response.json();

    console.log(result.message);
}

HTML/JSX:

<input type='file' name='fileInput' onChange={(e) => this.fileInput(e)} />

您可能不想使用onChange,但可以将上传部分附加到任何其他功能。


关于 jQuery 的问题,不是 React。 - Alessandro Lendaro

3
尝试使用此插件simpleUpload,无需表单即可实现。
<input type="file" name="arquivo" id="simpleUpload" multiple >
<button type="button" id="enviar">Enviar</button>

Javascript:

$('#simpleUpload').simpleUpload({
  url: 'upload.php',
  trigger: '#enviar',
  success: function(data){
    alert('Envio com sucesso');

  }
});

1
关于 jQuery 的问题,不是插件。 - Alessandro Lendaro

2

很抱歉我要这么说,但AngularJS提供了一种简单而优雅的解决方案。

以下是我使用的代码:

ngApp.controller('ngController', ['$upload',
function($upload) {

  $scope.Upload = function($files, index) {
    for (var i = 0; i < $files.length; i++) {
      var file = $files[i];
      $scope.upload = $upload.upload({
        file: file,
        url: '/File/Upload',
        data: {
          id: 1 //some data you want to send along with the file,
          name: 'ABC' //some data you want to send along with the file,
        },

      }).progress(function(evt) {

      }).success(function(data, status, headers, config) {
          alert('Upload done');
        }
      })
    .error(function(message) {
      alert('Upload failed');
    });
  }
};
}]);
.Hidden {
  display: none
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.0/jquery.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>

<div data-ng-controller="ngController">
  <input type="button" value="Browse" onclick="$(this).next().click();" />
  <input type="file" ng-file-select="Upload($files, 1)" class="Hidden" />
</div>

在服务器端,我有一个MVC控制器,它有一个操作来保存在Request.Files集合中找到的上传文件并返回JsonResult。如果您使用AngularJS,请尝试此方法,如果不使用...抱歉伙计 :-)

因为无法与$upload指令一起使用,所以被踩了。 - NicoJuicy
关于 jQuery 的问题,不是 AngularJS。 - Alessandro Lendaro

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接