通过 AJAX 和 jQuery 使用 HTML5 文件上传

问题描述:

诚然,Stack Overflow 上也有类似的问题,但似乎没有一个完全符合我的要求.

Admittedly, there are similar questions lying around on Stack Overflow, but it seems none quite meet my requirements.

这是我想要做的:

  • 上传完整形式的数据,其中一个是单个文件
  • 使用 Codeigniter 的文件上传库

到这里为止,一切都很好.数据在我需要时进入我的数据库.但我也想通过 AJAX 帖子提交我的表单:

Up until here, all is well. The data gets in my database as I need it. But I'd also like to submit my form via an AJAX post:

  • 使用原生 HTML5 文件 API,而不是 Flash 或 iframe 解决方案
  • 最好与低级 .ajax() jQuery 方法交互
  • Using the native HTML5 File API, not flash or an iframe solution
  • Preferably interfacing with the low-level .ajax() jQuery method

我想我可以想象如何通过在字段的值更改时使用纯 javascript 自动上传文件来做到这一点,但我宁愿一举完成这一切,以便在 jQuery 中提交.我认为通过查询字符串是不可能的,因为我需要传递整个文件对象,但我对此时要做什么有点迷茫.

I think I could imagine how to do this by auto-uploading the file when the field's value changes using pure javascript, but I'd rather do it all in one fell swoop on for submit in jQuery. I'm thinking it's not possible to do via query strings as I need to pass the entire file object, but I'm a little lost on what to do at this point.

这能实现吗?

这并不难.首先,看看FileReader Interface.

It's not too hard. Firstly, take a look at FileReader Interface.

所以,当表单提交时,抓住提交过程

So, when the form is submitted, catch the submission process and

var file = document.getElementById('fileBox').files[0]; //Files[0] = 1st file
var reader = new FileReader();
reader.readAsText(file, 'UTF-8');
reader.onload = shipOff;
//reader.onloadstart = ...
//reader.onprogress = ... <-- Allows you to update a progress bar.
//reader.onabort = ...
//reader.onerror = ...
//reader.onloadend = ...


function shipOff(event) {
    var result = event.target.result;
    var fileName = document.getElementById('fileBox').files[0].name; //Should be 'picture.jpg'
    $.post('/myscript.php', { data: result, name: fileName }, continueSubmission);
}

然后,在服务器端(即 myscript.php):

Then, on the server side (i.e. myscript.php):

$data = $_POST['data'];
$fileName = $_POST['name'];
$serverFile = time().$fileName;
$fp = fopen('/uploads/'.$serverFile,'w'); //Prepends timestamp to prevent overwriting
fwrite($fp, $data);
fclose($fp);
$returnData = array( "serverFile" => $serverFile );
echo json_encode($returnData);

或者类似的东西.我可能错了(如果我错了,请纠正我),但这应该将文件存储为 1287916771myPicture.jpg 在您的服务器上的 /uploads/ 中,并使用包含服务器上文件名的 JSON 变量(对 continueSubmission() 函数)进行响应.

Or something like it. I may be mistaken (and if I am, please, correct me), but this should store the file as something like 1287916771myPicture.jpg in /uploads/ on your server, and respond with a JSON variable (to a continueSubmission() function) containing the fileName on the server.

查看fwrite()jQuery.post().

在上面的页面上详细说明了如何使用 readAsBinaryString()代码>readAsDataUrl()readAsArrayBuffer() 用于其他需求(例如图片、视频等).

On the above page it details how to use readAsBinaryString(), readAsDataUrl(), and readAsArrayBuffer() for your other needs (e.g. images, videos, etc).