Im following this guide to use aJax to upload an image, mainly so I can have a progress bar. But for some reason the PHP script doesn't seem to receive a file!
Here is my JavaScript:
function submitFile() {
var form = document.forms.namedItem("imageUpload");
var formData = new FormData(form);
var xhr = new XMLHttpRequest();
xhr.open("POST", "php/uploadImage.php", true);
xhr.onload = function(e) {
if (xhr.status == 200) {
console.log("uploaded!");
doc("imageResponse").innerHTML = xhr.responseText;
} else {
console.log("error!");
doc("imageResponse").innerHTML += "Error " + xhr.status + " occurred when trying to upload your file.<br \/>";
}
};
//Progress
/*
xhr.upload.onprogress = function(e) {
if (e.lengthComputable) {
var currentPercentage = Math.round(e.loaded / e.total * 100);
document.getElementById("imageUpload").innerHTML = "UPLOAD IMAGE " + currentPercentage + "%";
document.getElementById("imageUpload").style.backgroundSize = currentPercentage + "% 100%";
}
};
*/
//Send data
xhr.send(formData);
}
And here is my PHP file which receives the file:
<?php
session_start();
print_r($_FILES);
?>
Currently that PHP file is returning an empty Array... it should have my file!
Array ( )
I managed to fix my code, here is the working version for anyone with the same problem. I decided to make a new form using JavaScript and append the file field value to this new form.
I did this mainly for my situation.
function submitFile(file,buttonId) {
//Generate a new form
var f = document.createElement("form");
f.setAttribute("method", "POST");
f.setAttribute("enctype", "multipart/form-data");
//Create FormData Object
var formData = new FormData(f);
//Append file
formData.append("image", file.files[0], "image.jpg");
var xhr = new XMLHttpRequest();
xhr.open("POST", "php/uploadImage.php", true);
xhr.onload = function(e) {
if (xhr.status == 200) {
document.getElementById(buttonId).innerHTML = "UPLOAD COMPLETE";
//console.log("uploaded!");
} else {
//console.log("error!");
alert("Error " + xhr.status + " occurred when trying to upload your file");
}
};
//Progress
xhr.upload.onprogress = function(e) {
if (e.lengthComputable) {
var currentPercentage = Math.round(e.loaded / e.total * 100)-1;
document.getElementById(buttonId).innerHTML = "UPLOAD IMAGE " + currentPercentage + "%";
document.getElementById(buttonId).style.backgroundSize = (currentPercentage+1) + "% 100%";
if (currentPercentage==99) {
document.getElementById(buttonId).innerHTML = "Processing image";
}
}
};
//Send data
xhr.send(formData);
}
Related
I use XMLHttpRequest to send POST data to nodejs (expressjs api). The size of file about 200mb. When I do, Chrome crashes, but the Firefox doesn't. Does Chrome have a limited file size?
And how can I upload the large file via JavaScript?
This is my code send xhr request:
// create http request API AI Engine
var xhr = new XMLHttpRequest();
xhr.open('POST', url, true);
xhr.responseType = 'arraybuffer';
xhr.timeout = 3600000;
xhr.onload = function() {
// reponse measage
if (this.status === 200) {
var errorArea = document.getElementById('error-area');
errorArea.style.display = 'none';
zip.files = {};
// unzip File
zip.loadAsync(this.response)
.then(function(zip) {
// will be called, even if content is corrupted
for (const file in zip.files) {
if (zip.files.hasOwnProperty(file)) {
const fileObject = zip.files[file];
fileObject.async('arraybuffer').then(function(fileData) {
var fileSave = new Blob([new Uint8Array(
fileData)]);
// Save file
saveAs(fileSave, fileObject.name);
})
}
}
}, function(e) {
var errorArea = document.getElementById('error-area');
errorArea.style.display = 'block';
errorArea.innerHTML =
'<strong>Error</strong> Cant not unzip file return.';
});
// get response stream data
} else {
var errorArea = document.getElementById('error-area');
errorArea.style.display = 'block';
errorArea.innerHTML =
'<strong>Error</strong> Cant not analyze file: ' + this.statusText;
}
};
// Handle when have error with xhr, show message
xhr.onerror = function(err) {
var errorArea = document.getElementById('error-area');
errorArea.style.display = 'block';
errorArea.innerHTML =
'<strong>Error</strong> Cant not analyze file: ' + this.statusText;
};
// Handle when have timeout with xhr, show message
xhr.ontimeout = function() {
var errorArea = document.getElementById('error-area');
errorArea.style.display = 'block';
errorArea.innerHTML =
'<strong>Error</strong> Cant not analyze file: Request time out';
};
// Add custom header
xhr.setRequestHeader('Content-type', 'application/octet-stream');
xhr.setRequestHeader('file-name', Date.now().toString() + '.zip');
xhr.setRequestHeader('file-length', data.byteLength);
// Send arraybuffer to server
xhr.send(data);
});
I don't know how to do that, only two files sent to the server at the same time just like here UploadImages.In my code all the files are sent all at the same time. Here is my code. Words needed to fill the post. Words needed to fill the post.
var percent_info = document.querySelectorAll('.progress_bar:not(.trans_completed) .percent');
var p_bar = document.querySelectorAll('.progress_bar:not(.trans_completed)');
/* --- Upload files to server loop --- */
for (var i = 0; i < files.length; i++) {
uploadFile(files[i], percent_info[i], p_bar[i]);
}
function uploadFile(file, percent_info, p_bar) {
var url = "server/index.php";
if (file.type.match(imageType)) {
var xhr = new XMLHttpRequest();
var fd = new FormData();
xhr.upload.addEventListener("progress", function(evt) {
if (evt.lengthComputable) {
var percentLoaded = Math.round((evt.loaded / evt.total) * 100);
if (percentLoaded < 100) {
percent_info.style.width = percentLoaded + "%";
}
}
});
xhr.upload.addEventListener("load", function(e) {
var percentLoaded = Math.round((e.loaded / e.total) * 100);
percent_info.style.width = percentLoaded + "%";
});
function ready() {
return function() {
if (xhr.readyState == 4 && xhr.status == 200) {
p_bar.classList.add('trans_completed');
}
};
}
xhr.onreadystatechange = ready();
xhr.open("POST", url, true);
fd.append('uploaded_file', file);
xhr.send(fd);
}
};
I am able to implement the image upload example found in the documentation of TinyMCE:
https://www.tinymce.com/docs/advanced/php-upload-handler/
My question is how can I show the user a specific error message when an error occurs? For example, if I upload an invalid file type, it only shows a generic 500 error message like this:
How can I show a more specific error message to the user like
"Invalid extension"?
Hi need to write your custom images_upload_handler.
In settings add this lines :
images_upload_handler : function handler(blobInfo, success, failure, progress) {
{
var valid_extensions = ['png','jpg']
var ext, extensions;
extensions = {
'image/jpeg': 'jpg',
'image/jpg': 'jpg',
'image/gif': 'gif',
'image/png': 'png'
};
ext = extensions[blobInfo.blob().type.toLowerCase()] || 'dat';
//add your extension test here.
if( valid_extensions.indexOf(ext) == -1){
failure("Invalid extension");
return;
}
var xhr, formData;
xhr = new XMLHttpRequest();
xhr.open('POST', settings.url);
xhr.withCredentials = settings.credentials;
xhr.upload.onprogress = function(e) {
progress(e.loaded / e.total * 100);
};
xhr.onerror = function() {
failure("Image upload failed due to a XHR Transport error. Code: " + xhr.status);
};
xhr.onload = function() {
var json;
if (xhr.status != 200) {
failure("HTTP Error: " + xhr.status);
return;
}
json = JSON.parse(xhr.responseText);
if (!json || typeof json.location != "string") {
failure("Invalid JSON: " + xhr.responseText);
return;
}
success(pathJoin(settings.basePath, json.location));
};
formData = new FormData();
formData.append('file', blobInfo.blob(), blobInfo.filename());
xhr.send(formData);
}
}
here is the upload logic in js
var upload = function(){
if(_file.files.length === 0){
return;
}
var data = new FormData();
data.append('SelectedFile', _file.files[0]);
var request = new XMLHttpRequest();
request.onreadystatechange = function(){
if(request.readyState == 4){
try {
var resp = JSON.parse(request.response);
} catch (e){
var resp = {
status: 'error',
data: 'Unknown error occurred: [' + request.responseText + ']'
};
}
console.log(resp.status + ': ' + resp.data);
}
};
request.upload.addEventListener('progress', function(e){
_progress.style.width = Math.ceil(e.loaded/e.total) * 100 + '%';
}, false);
request.open('POST', 'upload.php');
request.send(data);
}
I run the function every time user selected something, but I only got the first file if user selected multiple files.
That's because you're only adding the first file to your data object:
data.append('SelectedFile', _file.files[0]);
You need to add all your files in the _file.files collection
Something like:
for(var i = 0 ; i < _file.files.length; i++ ) {
data.append('SelectedFile'+i, _file.files[i]);
}
var data = new FormData();
data.append('SelectedFile', _file.files[0]);
Instead of this code, try something like this:
var data = new FormData();
for (var i in _file.files) data.append('SelectedFile'+i, _file.files[i]);
I have a piece of AS code that must be translated to javascript. Most of the things work okay now but only uploading (in chunks) fail. I get a message back from the server "Different file size". I think the way javascript post raw data differs from AS3's UrlRequest with FormData.
For example:
AS3: urlRequest.data = [ByteArray]
JS : Formdata.append('data', [FileBlob] )
Does this have the same result?
The AS3 code is:
private function sendData() : void
{
this._filePieceReadyToUpload = false;
this._bytesToSend = new ByteArray();
this._fileStream.readBytes(this._bytesToSend, 0, this._fileStream.bytesAvailable);
this._currentOperation = this.OP_DATA;
this._urlRequest = new URLRequest(_uploadScriptPath + "?op=" + this.OP_DATA + "&secure=" + _loginSecureHash + "&user_id=" + _userId + "&crc=" + this._headerCRC + "&size=" + this._bytesToSend.length + "&position=" + this._piecePosition + "&md5=" + this._fileCurrent.$md5 + "&api_id=" + _apiID);
this._urlRequest.method = URLRequestMethod.POST;
this._urlRequest.data = this._bytesToSend;
this.startURLRequstLoadTimer();
return;
}
Translated into this (javascript):
o.uploadFileBlob = function( blobFile, iBlobPos, sCrc )
{
var fd = new FormData();
fd.append( 'data', blobFile ),
xhr = new XMLHttpRequest(),
sGetVars = 'op=data'+
'&secure='+o.apik_secureHash+
'&user_id='+o.apik_userId+
'&crc='+sCrc+
'&size='+blobFile.size+
'&position='+iBlobPos+
'&md5='+
'&api_id=4';
xhr.upload.addEventListener("progress", function(e) { $d('progress'); }, false);
xhr.addEventListener("load" , function(e) { $d('upload complete'); }, false);
xhr.addEventListener("error", function(e) { $d('failed '+xhr.status+': '+xhr.statusText+' : '+xhr.responseText);
//alert( xhr.getAllResponseHeaders().toLowerCase() );
}, false);
xhr.addEventListener("abort", function(e) { $d('upload abort'); }, false);
xhr.open('POST', o.apik_address+'?'+sGetVars, true );
xhr.onload = function(e) { $d('xhr loaded'); };
return xhr.send(fd);
}
Can explain somebody to me what the difference is between the AS and JS version. Is a POST field 'data' in javascript the same as urlRequest.data in AS? What am I doing wrong?