So i am trying to upload an image along with form data to server. I'm using FileReader API to convert image to data and upload to server. I'm following the code similar to HTML5 uploader using AJAX Jquery.
The data is converted in jquery, but nothing is being sent to server and there is no error generated.
$('#formupload').on('submit', function(e){
e.preventDefault();
var hasError = false;
var file = document.getElementById('file').files[0];
var reader = new FileReader();
reader.readAsDataURL(file);
reader.onload = shipOff;
function shipOff(event) {
result = new Image();
result.src = event.target.result;
var fileName = document.getElementById('file').files[0].name;
$.post('test.php', { data: result, name: fileName });
}
PHP Code
<?php
$data = $_POST['data'];
$fileName = $_POST['name'];
echo $fileName;
$fp = fopen('/uploads/'.$fileName,'w'); //Prepends timestamp to prevent overwriting
fwrite($fp, $data);
fclose($fp);
$returnData = array( "serverFile" => $fileName );
echo json_encode($returnData);
?>
Is the problem due to large image file or FileReader API?
I'm not sure if file upload works with filereaders, but there is a different way to make it work:
var formData = new FormData($(".file_upload_form")[0]);
$.ajax({
url: "upload_file.php", // server script to process data (POST !!!)
type: 'POST',
xhr: function() { // custom xhr
myXhr = $.ajaxSettings.xhr();
if (myXhr.upload) { // check if upload property exists
// for handling the progress of the upload
myXhr.upload.addEventListener('progress', progressHandlingFunction, false);
}
return myXhr;
},
success: function(result) {
console.log($.ajaxSettings.xhr().upload);
alert(result);
},
// Form data
data: formData,
//Options to tell JQuery not to process data or worry about content-type
cache: false,
contentType: "application/octet-stream", // Helps recognize data as bytes
processData: false
});
function progressHandlingFunction(e) {
if (e.lengthComputable) {
$("#progress").text(e.loaded + " / " + e.total);
}
}
This way you send the data to the PHP file and you can use $_FILES to process it. Unfortunately, this does not work in IE as far as I know. There might be plugins available that make this possible in IE, but I don't know any of them.
Related
In my project I am using Symfony 3 + Filesaver.js and I need to download a .gz file. I do ajax request to my server with the following code:
function requestAjax(json_data) {
var request = $.ajax({
url: '/ajax'
, method: 'post'
, data: json_data
});
return request;
}
var json_text = {'type': 'download_file'};
var request = requestAjax(json_text);
request.done(function (response) {
var blob = new Blob(
[response], {
type: "text/plain;charset=" + document.characterSet});
saveAs(blob, 'filename.gz');
});
On php side I do the following:
$myfile = '/opt/myfile.gz';
$fp = fopen($myfile, "rb");
$response = base64_encode(fread($fp, filesize($myfile)));
fclose($fp);
return new Response($response);
But when I try to open my downloaded file, I get an error that the file is broken and cannot be read (still I can read it on my server and I know that the file is ok). So the question is how to download a .gz file with an ajax call in php + javascript. Thank you.
I want to implement a simple file upload in my intranet-page, with the smallest setup possible.
This is my HTML part:
<input id="sortpicture" type="file" name="sortpic" />
<button id="upload">Upload</button>
and this is my JS jquery script:
$("#upload").on("click", function() {
var file_data = $("#sortpicture").prop("files")[0];
var form_data = new FormData();
form_data.append("file", file_data);
alert(form_data);
$.ajax({
url: "/uploads",
dataType: 'script',
cache: false,
contentType: false,
processData: false,
data: form_data,
type: 'post',
success: function(){
alert("works");
}
});
});
There is a folder named "uploads" in the root directory of the website, with change permissions for "users" and "IIS_users".
When I select a file with the file-form and press the upload button, the first alert returns "[object FormData]". the second alert doesn't get called and the"uploads" folder is empty too!?
Can someone help my finding out whats wrong?
Also the next step should be, to rename the file with a server side generated name. Maybe someone can give me a solution for this, too.
You need a script that runs on the server to move the file to the uploads directory. The jQuery ajax method (running on the client in the browser) sends the form data to the server, then a script running on the server handles the upload.
Your HTML is fine, but update your JS jQuery script to look like this:
(Look for comments after // <-- )
$('#upload').on('click', function() {
var file_data = $('#sortpicture').prop('files')[0];
var form_data = new FormData();
form_data.append('file', file_data);
alert(form_data);
$.ajax({
url: 'upload.php', // <-- point to server-side PHP script
dataType: 'text', // <-- what to expect back from the PHP script, if anything
cache: false,
contentType: false,
processData: false,
data: form_data,
type: 'post',
success: function(php_script_response){
alert(php_script_response); // <-- display response from the PHP script, if any
}
});
});
And now for the server-side script, using PHP in this case.
upload.php: a PHP script that is located and runs on the server, and directs the file to the uploads directory:
<?php
if ( 0 < $_FILES['file']['error'] ) {
echo 'Error: ' . $_FILES['file']['error'] . '<br>';
}
else {
move_uploaded_file($_FILES['file']['tmp_name'], 'uploads/' . $_FILES['file']['name']);
}
?>
Also, a couple things about the destination directory:
Make sure you have the correct server path, i.e., starting at the PHP script location what is the path to the uploads directory, and
Make sure it's writeable.
And a little bit about the PHP function move_uploaded_file, used in the upload.php script:
move_uploaded_file(
// this is where the file is temporarily stored on the server when uploaded
// do not change this
$_FILES['file']['tmp_name'],
// this is where you want to put the file and what you want to name it
// in this case we are putting in a directory called "uploads"
// and giving it the original filename
'uploads/' . $_FILES['file']['name']
);
$_FILES['file']['name'] is the name of the file as it is uploaded. You don't have to use that. You can give the file any name (server filesystem compatible) you want:
move_uploaded_file(
$_FILES['file']['tmp_name'],
'uploads/my_new_filename.whatever'
);
And finally, be aware of your PHP upload_max_filesize AND post_max_size configuration values, and be sure your test files do not exceed either. Here's some help how you check PHP configuration and how you set max filesize and post settings.
**1. index.php**
<body>
<span id="msg" style="color:red"></span><br/>
<input type="file" id="photo"><br/>
<script type="text/javascript" src="jquery-3.2.1.min.js"></script>
<script type="text/javascript">
$(document).ready(function(){
$(document).on('change','#photo',function(){
var property = document.getElementById('photo').files[0];
var image_name = property.name;
var image_extension = image_name.split('.').pop().toLowerCase();
if(jQuery.inArray(image_extension,['gif','jpg','jpeg','']) == -1){
alert("Invalid image file");
}
var form_data = new FormData();
form_data.append("file",property);
$.ajax({
url:'upload.php',
method:'POST',
data:form_data,
contentType:false,
cache:false,
processData:false,
beforeSend:function(){
$('#msg').html('Loading......');
},
success:function(data){
console.log(data);
$('#msg').html(data);
}
});
});
});
</script>
</body>
**2.upload.php**
<?php
if($_FILES['file']['name'] != ''){
$test = explode('.', $_FILES['file']['name']);
$extension = end($test);
$name = rand(100,999).'.'.$extension;
$location = 'uploads/'.$name;
move_uploaded_file($_FILES['file']['tmp_name'], $location);
echo '<img src="'.$location.'" height="100" width="100" />';
}
Use pure js
async function saveFile()
{
let formData = new FormData();
formData.append("file", sortpicture.files[0]);
await fetch('/uploads', {method: "POST", body: formData});
alert('works');
}
<input id="sortpicture" type="file" name="sortpic" />
<button id="upload" onclick="saveFile()">Upload</button>
<br>Before click upload look on chrome>console>network (in this snipped we will see 404)
The filename is automatically included to request and server can read it, the 'content-type' is automatically set to 'multipart/form-data'. Here is more developed example with error handling and additional json sending
async function saveFile(inp)
{
let user = { name:'john', age:34 };
let formData = new FormData();
let photo = inp.files[0];
formData.append("photo", photo);
formData.append("user", JSON.stringify(user));
try {
let r = await fetch('/upload/image', {method: "POST", body: formData});
console.log('HTTP response code:',r.status);
alert('success');
} catch(e) {
console.log('Huston we have problem...:', e);
}
}
<input type="file" onchange="saveFile(this)" >
<br><br>
Before selecting the file Open chrome console > network tab to see the request details.
<br><br>
<small>Because in this example we send request to https://stacksnippets.net/upload/image the response code will be 404 ofcourse...</small>
var formData = new FormData($("#YOUR_FORM_ID")[0]);
$.ajax({
url: "upload.php",
type: "POST",
data : formData,
processData: false,
contentType: false,
beforeSend: function() {
},
success: function(data){
},
error: function(xhr, ajaxOptions, thrownError) {
console.log(thrownError + "\r\n" + xhr.statusText + "\r\n" + xhr.responseText);
}
});
and this is the php file to receive the uplaoded files
<?
$data = array();
//check with your logic
if (isset($_FILES)) {
$error = false;
$files = array();
$uploaddir = $target_dir;
foreach ($_FILES as $file) {
if (move_uploaded_file($file['tmp_name'], $uploaddir . basename( $file['name']))) {
$files[] = $uploaddir . $file['name'];
} else {
$error = true;
}
}
$data = ($error) ? array('error' => 'There was an error uploading your files') : array('files' => $files);
} else {
$data = array('success' => 'NO FILES ARE SENT','formData' => $_REQUEST);
}
echo json_encode($data);
?>
I want to implement a simple file upload in my intranet-page, with the smallest setup possible.
This is my HTML part:
<input id="sortpicture" type="file" name="sortpic" />
<button id="upload">Upload</button>
and this is my JS jquery script:
$("#upload").on("click", function() {
var file_data = $("#sortpicture").prop("files")[0];
var form_data = new FormData();
form_data.append("file", file_data);
alert(form_data);
$.ajax({
url: "/uploads",
dataType: 'script',
cache: false,
contentType: false,
processData: false,
data: form_data,
type: 'post',
success: function(){
alert("works");
}
});
});
There is a folder named "uploads" in the root directory of the website, with change permissions for "users" and "IIS_users".
When I select a file with the file-form and press the upload button, the first alert returns "[object FormData]". the second alert doesn't get called and the"uploads" folder is empty too!?
Can someone help my finding out whats wrong?
Also the next step should be, to rename the file with a server side generated name. Maybe someone can give me a solution for this, too.
You need a script that runs on the server to move the file to the uploads directory. The jQuery ajax method (running on the client in the browser) sends the form data to the server, then a script running on the server handles the upload.
Your HTML is fine, but update your JS jQuery script to look like this:
(Look for comments after // <-- )
$('#upload').on('click', function() {
var file_data = $('#sortpicture').prop('files')[0];
var form_data = new FormData();
form_data.append('file', file_data);
alert(form_data);
$.ajax({
url: 'upload.php', // <-- point to server-side PHP script
dataType: 'text', // <-- what to expect back from the PHP script, if anything
cache: false,
contentType: false,
processData: false,
data: form_data,
type: 'post',
success: function(php_script_response){
alert(php_script_response); // <-- display response from the PHP script, if any
}
});
});
And now for the server-side script, using PHP in this case.
upload.php: a PHP script that is located and runs on the server, and directs the file to the uploads directory:
<?php
if ( 0 < $_FILES['file']['error'] ) {
echo 'Error: ' . $_FILES['file']['error'] . '<br>';
}
else {
move_uploaded_file($_FILES['file']['tmp_name'], 'uploads/' . $_FILES['file']['name']);
}
?>
Also, a couple things about the destination directory:
Make sure you have the correct server path, i.e., starting at the PHP script location what is the path to the uploads directory, and
Make sure it's writeable.
And a little bit about the PHP function move_uploaded_file, used in the upload.php script:
move_uploaded_file(
// this is where the file is temporarily stored on the server when uploaded
// do not change this
$_FILES['file']['tmp_name'],
// this is where you want to put the file and what you want to name it
// in this case we are putting in a directory called "uploads"
// and giving it the original filename
'uploads/' . $_FILES['file']['name']
);
$_FILES['file']['name'] is the name of the file as it is uploaded. You don't have to use that. You can give the file any name (server filesystem compatible) you want:
move_uploaded_file(
$_FILES['file']['tmp_name'],
'uploads/my_new_filename.whatever'
);
And finally, be aware of your PHP upload_max_filesize AND post_max_size configuration values, and be sure your test files do not exceed either. Here's some help how you check PHP configuration and how you set max filesize and post settings.
**1. index.php**
<body>
<span id="msg" style="color:red"></span><br/>
<input type="file" id="photo"><br/>
<script type="text/javascript" src="jquery-3.2.1.min.js"></script>
<script type="text/javascript">
$(document).ready(function(){
$(document).on('change','#photo',function(){
var property = document.getElementById('photo').files[0];
var image_name = property.name;
var image_extension = image_name.split('.').pop().toLowerCase();
if(jQuery.inArray(image_extension,['gif','jpg','jpeg','']) == -1){
alert("Invalid image file");
}
var form_data = new FormData();
form_data.append("file",property);
$.ajax({
url:'upload.php',
method:'POST',
data:form_data,
contentType:false,
cache:false,
processData:false,
beforeSend:function(){
$('#msg').html('Loading......');
},
success:function(data){
console.log(data);
$('#msg').html(data);
}
});
});
});
</script>
</body>
**2.upload.php**
<?php
if($_FILES['file']['name'] != ''){
$test = explode('.', $_FILES['file']['name']);
$extension = end($test);
$name = rand(100,999).'.'.$extension;
$location = 'uploads/'.$name;
move_uploaded_file($_FILES['file']['tmp_name'], $location);
echo '<img src="'.$location.'" height="100" width="100" />';
}
Use pure js
async function saveFile()
{
let formData = new FormData();
formData.append("file", sortpicture.files[0]);
await fetch('/uploads', {method: "POST", body: formData});
alert('works');
}
<input id="sortpicture" type="file" name="sortpic" />
<button id="upload" onclick="saveFile()">Upload</button>
<br>Before click upload look on chrome>console>network (in this snipped we will see 404)
The filename is automatically included to request and server can read it, the 'content-type' is automatically set to 'multipart/form-data'. Here is more developed example with error handling and additional json sending
async function saveFile(inp)
{
let user = { name:'john', age:34 };
let formData = new FormData();
let photo = inp.files[0];
formData.append("photo", photo);
formData.append("user", JSON.stringify(user));
try {
let r = await fetch('/upload/image', {method: "POST", body: formData});
console.log('HTTP response code:',r.status);
alert('success');
} catch(e) {
console.log('Huston we have problem...:', e);
}
}
<input type="file" onchange="saveFile(this)" >
<br><br>
Before selecting the file Open chrome console > network tab to see the request details.
<br><br>
<small>Because in this example we send request to https://stacksnippets.net/upload/image the response code will be 404 ofcourse...</small>
var formData = new FormData($("#YOUR_FORM_ID")[0]);
$.ajax({
url: "upload.php",
type: "POST",
data : formData,
processData: false,
contentType: false,
beforeSend: function() {
},
success: function(data){
},
error: function(xhr, ajaxOptions, thrownError) {
console.log(thrownError + "\r\n" + xhr.statusText + "\r\n" + xhr.responseText);
}
});
and this is the php file to receive the uplaoded files
<?
$data = array();
//check with your logic
if (isset($_FILES)) {
$error = false;
$files = array();
$uploaddir = $target_dir;
foreach ($_FILES as $file) {
if (move_uploaded_file($file['tmp_name'], $uploaddir . basename( $file['name']))) {
$files[] = $uploaddir . $file['name'];
} else {
$error = true;
}
}
$data = ($error) ? array('error' => 'There was an error uploading your files') : array('files' => $files);
} else {
$data = array('success' => 'NO FILES ARE SENT','formData' => $_REQUEST);
}
echo json_encode($data);
?>
I am trying to upload images via an AJAX call and Codeigniter:
My View:
<?php echo form_open_multipart('upload/do_upload'); ?>
<input type="file" name="userfile" id="userfile" size="20" />
<br />
<input type="submit" value="upload" id="upload_file_1" />
</form>
My Ajax Call:
$(document).ready(function(){
$(function() {
$('#upload_file_1').click(function(e) {
e.preventDefault();
var filename = $("#userfile").val();
$.ajax({
url :'index.php/upload/do_upload',
secureuri :false,
fileElementId: 'userfile',
dataType : 'json',
type : 'POST',
done : function (data)
{
alert(data);
}
});
});
});
});
and my controller:
class Upload extends CI_Controller {
function __construct() {
parent::__construct();
$this->load->helper(array('form', 'url'));
}
function index() {
$this->load->view('upload_form', array('error' => ' '));
}
function do_upload() {
$config['upload_path'] = './uploads/';
$config['allowed_types'] = 'gif|jpg|png';
$config['max_size'] = '1000000';
$config['max_width'] = '10240';
$config['max_height'] = '7680';
$this->load->library('upload', $config);
if (!$this->upload->do_upload('userfile')) {
$error = array('error' => $this->upload->display_errors());
echo "error!";
echo "<pre>";
print_r($error);
echo "<pre/>";
} else {
echo "done!";
}
}
}
but it gives me an error saying : "You did not select a file to upload. "; without AJAX it works fine, probably my AJAX call is not right! Could you please let me know if I am doing something wrong?
Thanks
In my very recent project i used below code to upload files with formdata asynchronously using jquery ajax,
However i was not able to upload files with success: function() of jQuery so i used complete to process server response. You can try with success:function().
You will receive your data in $_Post & file in $_FILES variable.
If only want to upload files. change it like wise.
Hope this will help you.
Also look at this tutorial:http://abandon.ie/notebook/simple-file-uploads-using-jquery-ajax
function frm_submit(){
var form = new FormData(document.getElementById('frmSample')); //frmSample is form id
var file = document.getElementById('userfile').files[0]; //userfile file tag id
if (file) {
form.append('userfile', file);
}
$.ajax({
url: 'path/to/upload/script',
type: 'POST',
xhr: function() { // custom xhr
//progressHandlingFunction to hangle file progress
var myXhr = $.ajaxSettings.xhr();
if (myXhr.upload) { // check if upload property exists
myXhr.upload.addEventListener('progress', progressHandlingFunction, false); // for handling the progress of the upload
}
return myXhr;
},
data: form,
cache: false,
contentType: false, //must
processData: false, //must
complete: function(XMLHttpRequest) {
var data = JSON.parse(XMLHttpRequest.responseText);
console.log(data);
console.log('complete');
},
error: function() {
console.log('error');
}
}).done(function() {
console.log('Done Sending messages');
}).fail(function() {
console.log('message sending failed');
});
}//function frm_submit ends here
i used this javascript library
https://github.com/blueimp/jQuery-File-Upload
and got file uploading working with ajax - drag/drop + progress bars, and returns the appropriate file icon or image thumbnail that could be downloaded straight away. it was quite difficult to get it fully working and abstracted so the same routine handled multiple types of uploads each with their own restrictions.
the link will give some basic example code, it is worth a look.
pete
I'm trying to let users import an OPML file that I parse server (rails app) side. I'm having trouble as it seems that my server isn't getting the info (neither the success nor error functions run and even if I hardcode other data into the call, the call doesn't change).
Here's what I have embedded into the page:
<script>
function handleFileSelect(evt) {
var files = evt.target.files; // FileList object
// Loop through the FileList
for (var i = 0, f; f = files[i]; i++) {
var reader = new FileReader();
// Closure to capture the file information.
reader.onload = (function(theFile) {
return function(e) {
// Print the contents of the file
var span = document.createElement('span');
span.innerHTML = ['<p>',e.target.result,'</p>'].join('');
document.getElementById('list').insertBefore(span, null);
};
$.ajax({
type: 'GET',
url: "/parse_opml",
data: {file: f},
success: function(details, response) {
console.log('woo!');
},
error: function(data, response) {
console.log('boooo');
}
});
})(f);
// Read in the file
reader.readAsText(f);
}
}
document.getElementById('the_o').addEventListener('change', handleFileSelect, false);
</script>
<input id="the_o" name="files[]" type="file">
Looking at chrome's network panel, I'm seeing the call: Request URL:blob:http%3A//localhost%3A3000/14e2be6b-059f-47f5-ba37-97eda06242b4 whose preview and response is the content of my .txt file. But like I said, the server never gets that text, so I'm puzzled.
Any help is greatly appreciated, thanks!
ANSWER
I ended up just using this: JavaScript: Upload file
Client code:
%form{:enctype => 'multipart/form-data', :action => '/parse_opml', :method => 'post'}
%input{:type => 'file', :name => 'file', :id => 'the_o'}
%input{:type => 'submit', :value => 'go'}
Server code:
f = File.open(params[:file].tempfile, 'r')
c = f.read
Works like a charm!
Javascript can't post uploaded files to the server as it is a limitation (for security reasons I assume).
Take a look at this other question regarding posting files posted through javascript:
JavaScript: Upload file
The answer on that questions says you can only do it using flash, but there are also iframe alternatives for upload and post.
Take a look at this as well for an alternative solution:
https://github.com/Widen/fine-uploader
Your ajax request isn't event sent as you return from your onload function before it.
You can send files via ajax on up to date browsers using XHR2
reader.onload = (function(theFile) {
var data = new FormData();
data.append('file',theFile);
$.ajax({
type: 'POST',
processData: false,
contentType: false,
url: "/parse_opml",
data: data,
success: function(details, response) {
console.log('woo!');
},
error: function(data, response) {
console.log('boooo');
}
});
return function(e) {
// Print the contents of the file
var span = document.createElement('span');
span.innerHTML = ['<p>',e.target.result,'</p>'].join('');
document.getElementById('list').insertBefore(span, null);
};
})(f);