提交HTML表单数据作为一个文件/组合表单数据+文件,并在Javascript中作为单个文件发送


Submit HTML form data as a file / Combine form data + file and send as single file in Javascript

我有一个表单,输入字段像一些文本字段,文本区域,下拉框和文件上传字段,用户将在填写表单时上传,我想发送表单内容(两个表单字段值+上传的文件)作为一个文件到服务器下面是我的问题的一个非常简化的版本。说我有以下标记

<form id="myForm" method="post" action="something">
  <input type="text" name="username" id="username">
  <input type="text" name="email"  id="email">
  <input type="file" name="myFile"   id="myFile">
</form>

所以现在我想要的是,而不是分别发送以上2个文本字段和一个文件,我想让他们嵌入到一个文件,然后作为一个整体发送。示例

请注意,我发送的服务器是第三方的,除了文件,文件格式也是专有的,但它仍然是ASCII纯文本。我意识到这只能通过AJAX和fileReader API实现,所以这就是我所尝试的

 var file;
 $('#myFile').change(function(e){
    file = this.files[0];
    var fr = new FileReader();
    fr.onload = function(event){
        fileData = fr.result;
    };
    fr.readAsDataURL(file);
  $('#myForm').submit(function(e){
    e.preventDefault();//prevent submit
    var myFile= [$('#username').val(),$('#email').val(),fileData];
    $.ajax({
      url : "some url",
      type: "POST",
      contentType:false,
      processData:false,
      data: myFile;
      success:function(data){ }
    });
 });

问题是表单提交后没有文件被发送。任何帮助将非常感激,谢谢。

在表单提交中,您可以按照以下方法使用AJAX请求发送文件

$('#myform').submit(function(e){
    e.preventDefault();//prevent submit
    var form_data = new FormData();                  
    form_data.append('file', $('#myfile').prop('files')[0]);
    form_data.append('username', $("#username").val());
    form_data.append('phone', $("#phone").val());
    $.ajax({
      url : "some url",
      type: "POST",
      contentType:false,
      processData:false,
      data: form_data;
      success:function(data){ }
    });
 });

有两部分

  1. 将文件转换为字符串格式或在客户端使用FileReader API序列化
  2. 将您的表单值与此字符串合并并作为文件发送。

我不知道你是否注意到但是当你使用readAsDataURL()时,你不会得到原始文件字节流,而是得到base64编码的版本,所以记住这一点,将代码更改为

var fileData;
$('#myFile').change(function(e){
    file = this.files[0];
    var fr = new FileReader();
    fr.onload = function(event) {
        encfileData = fr.result;
        startInx = encfileData.indexOf('base64');
        startInx += 7;
        tmp = encfileData.substr(startInx);
        //removes the file MIME header part ie. "data:text/plain;base64," before decoding
        //regex may be preferable
        fileData = atob(tmp); //DECODE
    };
    fr.readAsDataURL(file);
});

所以现在你有一个字符串包含你的文件的字节流,现在正如你所说的,有一些格式,所以取决于你做任何操作,你可能需要使它与格式对齐,因为你已经提到了它的纯文本格式,所以基本的字符串函数在这里是足够的。对于下一部分,我假设基于简单冒号的CSV格式key1:value1,key2:value2

第二部分

现在要真正凭空创建一个文件,你可以使用file或Blob,但我建议使用Blob,因为它的支持更好。要包含需要FormData的文件,只需将blob附加到它并发送

$('#myForm').submit(function(e){
    e.preventDefault();
    var txtData = "'n username:"+$("#username").val()+","+"email:"+$("#email").val();
    // NOTE: windows uses 'r'n instead of 'n for newlines
    var payLoad =  fileData + txtData;  //append text field data to the file data
    var blob = new Blob([payLoad], {type : 'plain/txt'});
    var form = new FormData();
    var fileName = 'combined.txt';    //filename that will be used on server
    form.append('something', blob, fileName);
    $.ajax({
        url: "some url",
        type: "POST",
        cache: false,
        contentType: false,
        processData: false,
        data: form,
        success: function(response){alert(response);}
    });     
});

如果在linux上使用php,你的$_FILES应该看起来像这样

Array
(
    [something] => Array
    (
        [name] => combined.txt
        [type] => plain/txt
        [tmp_name] => /tmp/phpJvSJ94
        [error] => 0
        [size] => 95
    )
)

似乎你正在传递发送错误的变量在你的AJAX有效载荷-你不应该发送fileData而不是file吗?

您可以上传数据和文件:

<form id="data" method="post" enctype="multipart/form-data">
  <input type="text" name="username" id="username">
  <input type="text" name="email"  id="email">
  <input type="file" name="myFile"   id="myFile">
</form>
Jquery

$("form#data").submit(function(){
var formData = new FormData($(this)[0]);
$.ajax({
    url: 'your_url',
    type: 'POST',
    data: formData,
    async: false,
    success: function (data) {
        alert(data)
    },
    cache: false,
    contentType: false,
    processData: false
});
return false;
});