Upload file from HTML5 Filesystem by XMLHttpRequest

久未见 提交于 2019-12-01 01:28:18

this is the Javascript function that worked for me in chrome

function upload(filename) {	

	var xhr = new XMLHttpRequest();
	xhr.open("post", "upload.php", true);

	window.resolveLocalFileSystemURL = window.resolveLocalFileSystemURL || window.webkitResolveLocalFileSystemURL;

	filename = 'filesystem:http://localhost/temporary/' + filename;
	window.resolveLocalFileSystemURL(filename, function(fileEntry) {		
		fileEntry.file(function(file) {
			xhr.setRequestHeader("Content-Type", "multipart/form-data");
			xhr.setRequestHeader("X-File-Name", file.name);
			xhr.setRequestHeader("X-File-Size", file.size);
			xhr.setRequestHeader("X-File-Type", file.type);
		    xhr.send(file);
		});
	});

}

Now most people on the skip the upload.php taking it for granted. But it is very important and so I paste it here:

<?php
    // I had to figure out what is getting passed using var_dump($_SERVER)
	$fn = (isset($_SERVER['HTTP_X_FILE_NAME']) ? $_SERVER['HTTP_X_FILE_NAME'] : false);
	if ($fn) {
		// AJAX call
		file_put_contents(
			'uploads/' . $fn,
			file_get_contents('php://input')
		);
		echo "$fn uploaded";
		exit();	
	}
?>

Hope this helps someone, I wasted an entire day to figure this out !

First of all, your comment isn't exactly correct, the PHP code shouldn't even be receiving a blob. It's just receiving text, because you read the file as text, while png images (and almost all image types) aren't supposed to be text, they're supposed to be binary. And Blobs themselves are perfect for storing binary data, so you don't even need to use a FileReader, you can just send the Blob itself through XMLHttpRequest!

Here is how the revised fileEntry.file callback function should look:

fileEntry.file(function(file) {
    xhr.send(file);
});

It's that simple! No need to read the Blob. However, you need to do some more stuff on the PHP side now. This code will write the contents of the uploaded image to disk, then create an <img> element that allows you to view it. Here's how the PHP /posttest.php should look for that:

<?php
$rhand=fopen('php://input','r');
$cont=fread($rhand,filesize('php://input'));
fclose($rhand);
$whand=fopen('./uploaded.png','w');
fwrite($whand,$cont);
fclose($whand);
?>
<img src="uploaded.png">

It should be pretty clear what that does if you know that php://input is where php will get input from a post request if it doesn't have a MIME type that allows it to easily put it into $_POST (For example, when you have have a request with MIME type application/x-www-form-urlencoded, PHP recognizes it and is able to parse the POST contents into $_POST, but with a Blob, it doesn't, so it just outputs it out of php://input)

Please note that none of this is tested, please put a comment if it doesn't work and I'll try to fix it!

Having encountered the same challenge myself, I was able to come up with a very sleek solution. The key is to create a new Blob, from the file object returned by the fileEntry.

window.resolveLocalFileSystemURL = window.resolveLocalFileSystemURL || window.webkitResolveLocalFileSystemURL;

    window.resolveLocalFileSystemURL(image, function (fileEntry) {
        fileEntry.file(function (file) {
            var formData = new FormData();
            var tempBlob=new Blob([this.result], {type:this.result.type});
            formData.append('image', tempBlob);

        });
    });
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!