Uploading large videos & Audio files to server using XMLHttpRequest - javascript

I have a form that has been working perfectly fine when it comes to uploading files and large images. For any image that is too large it gets resized using a canvas and then I append it to the form Data and it saves perfectly. However I have now been asked to allow videos and audio files to be uploaded on the same file input.
This sort of has thrown me for a bit of a loop because even shorter videos from a phone can be 50MB or more especially if the quality of the camera is good. I searched for a number of things but I can't seem to find something that already somewhat works with the submission process I have going on.
I saw I can split the file into chunks and upload it in pieces to the server, but the other unfortunate part is when I submit the file (image, pdf, mp4, mp3) I am also submitting other information, like Description (small paragraph describing the file), name of person submitting the file etc.
My current process goes a little something like this:
Person uploads file + information, I send it away using formData and new XMLHttpRequest().
On the server side I get the name, set the path and get a date for the submission. The name of the image/file gets changed to be something like 20200128200812_imageName.jpeg which helps me retrieve the image based on what time the form was submitted (database column frmSubmitted).
What I am attempting to do:
Allow a user submit a form with the ability to process video types and audio types but still process the information that is associated with the file, like name or description.
I'm afraid if I submit the video or audio file in chunks, I will be also submitting the other information as well, I might be wrong on this but all other posts I have read seem to mention making separate requests might be the only way to do this. The following code works and is how I am currently set up but I am including it for context.
html
<input type="text" id="name"/>
<textarea id="description" name="description" rows="5" cols="50" maxlength="2000"></textarea>
<input type="file" name="sFile" id="sFile" multiple />
<button onclick="submitFile();" class="btn" >submit</button>
JS
function submitFile(){
const files= document.querySelector('#sFile').files;
var formData = new FormData();
if (files.length > 0){
for (var i = 0; i < files.length; i++) {
var file= files[i];
if(checkFileExtension(file) && checkFileSize(file)){ //checks the file for images and the size of the image
image = resizeImage(file);
formData.append('images[]', image);
}else{
formData.append(file[], file);
}
}
}
/*
*getting values & error handling...
*/
//appending values
formData.append('desc', description);
formData.append('personName', name);
var postrequest = new XMLHttpRequest();
postrequest.open('post', 'include/fileProcessing.php', true);
postrequest.send(formData);
postrequest.onload = function(){
var data = JSON.parse(postrequest.responseText);
if(data.result == 'true' ){
alert('Form has been submitted!');
}
php
$date = date('YmdHis');
if (isset($_FILES['images'])) {
$errors = [];
$path = '../images/uploads/';
$extensions = ['jpg', 'jpeg', 'png', 'gif', 'doc', 'docx', 'pdf'];
$all_files = count($_FILES['images']['tmp_name']);
for ($i = 0; $i < $all_files; $i++) {
$original_Name = $_FILES['images']['name'][$i];
$file_name = $date .'_'.$original_Name;
$file_tmp = $_FILES['images']['tmp_name'][$i];
$file_type = $_FILES['images']['type'][$i];
$file_size = $_FILES['images']['size'][$i]/1024;
$file_ext = strtolower(end(explode('.', $_FILES['images']['name'][$i])));
if (!in_array($file_ext, $extensions)) {
$errors[] = 'Image type not allowed: ' . $original_Name . ' ' . $file_type;
}
if ($file_size > 2097152) {
$errors = 'Image size too large';
}
$file = $path . $file_name;
if (empty($errors)) {
move_uploaded_file($file_tmp, $file);
}
}
if ($errors) $rtVariables['picErrors'] = $errors;
}
/**check and upload files that are not images but too long to post**/
Any help would be greatly appreciated.

Related

Problems with displaying text in Javascript "N�O�T�I�C�E�", php displays it with no problem

PHP creates the text from metadata from image file which stores it in variable of the same name of IMG source.
No Problems
JavaScript displays the gallery to show images, scroll & enlarge.
During enlargement it gives description of image from source attribute but always displays the text with � after every character. But PHP doesn't.
I've tried encoding which you will see from code & & echo header("Content-Type: text/html; charset=ISO-8859-1");
PHP:
$path = "gallery/";
$objs = new RecursiveIteratorIterator(new
RecursiveDirectoryIterator($path),
RecursiveIteratorIterator::SELF_FIRST);
$num = 0;
foreach ($objs as $pic){
$pic = str_replace('gallery/', '', $pic);
if ($pic == '..' or $pic == '.'){
continue;
}
$exif = exif_read_data("$DIR/gallery/$pic", 0, true);
$pic = str_replace('.JPG', '', $pic);
${$pic} = $exif['IFD0']['Comments']; ///// php Variable
echo "<script> var $pic = '".$exif['IFD0']['Comments']."';
var $pic = utf8_encode($pic);</script>";
// JS of variable of same name.
}
Sloppy but Works
JQuery:
$('#mSide').on('click',function(){
var src = $('#mPic').attr('src');
var v = src.replace('/gallery/','');
v = v.replace('.JPG','');
v = unescape(encodeURIComponent(v));
$('#fullPic').show();
$('#fullPic').append('<img class=\"fPic\" src=\"'+src+'\"
height=\"90%\" widdth=\"90%\" style=\"margin-left:0px;\" />');
$('#fullPic').append('<span id=\"picSummary\"
style=\"color:#FFFFFF;\" >testing <textarea > '+ window[v] +'</textarea>
</span>');
$('#fullPic').prepend('<input class=\"closeFullP headr\"
value=\"Close\" READONLY><br class=\"closeFullP\">');
});
Sloppy but Works and window[v] is the call
Should display: this is the new val = NOTICE: This e-mail message may contain legally privileged and/or confidential information. If you are not the intended recipient, you are hereby notified that any dissemination of the contents of this message is strictly prohibited. If you have received this message in error, please immediately notify the sender at ########### and delete all copies of this e-mail message and its attachments.
Not: N�O�T�I�C�E�:� �T�h�i�s� �e�-�m�a�i�l�
�m�e�s�s�a�g�e� �m�a�y� �c�o�n�t�a�i�n�
�l�e�g�a�l�l�y� �p�r�i�v�i�l�e�g�e�d� �a�n�d�/�o�r�
�c�o�n�f�i�d�e�n�t�i�a�l� �i�n�f�o�r�m�a�t�i�o�n�.�
�I�f� �y�o�u� �a�r�e� �n�o�t� �t�h�e�
�i�n�t�e�n�d�e�d� �r�e�c�i�p�i�e�n�t�,...............
Never use utf8_encode() or utf8_decode() they make awful assumptions and happily/silently corrupt your data. Always use a function that allows you to explicitly specify your input and output encodings.
The data you're extracting from EXIF is encoded as UTF16-LE, and your page is... something else. I can't tell what and you should probably figure that out and be consistent.
Suggested reading: UTF-8 all the way through
If your page is encoded as ISO-8859-1:
$proper = mb_convert_encoding($input, 'ISO-8859-1', 'UTF-16-LE');
If your page is encoded as UTF-8:
$proper = mb_convert_encoding($input, 'UTF-8', 'UTF-16-LE');
Ref: https://secure.php.net/manual/en/function.mb-convert-encoding.php

How can I enable user to select one image from the multiple images that he has just uploaded without refreshing the page?

I have a form where user can upload multiple images. I need a way to enable user to select one image from the images he just uploaded as his main picture before submitting the form.
I have loaded the previews using JavaScript file reader. I have tried to add a name via JavaScript to the image user has selected, so it can be accessed as a post element in the PHP script. But it is not working since it cannot be accessed as a file. I have spent 3 full days over this before posting this question. It'll be a huge help I anyone could tell me on how to approach this problem.
Following is the form :
<input type="file" name="files[]" multiple="true" id="file">
<div class="list"></div>
Javascript code for loading previews:
var imagesPreview = function(input, p) {
var id=1;
if (input.files) {
var filesAmount = input.files.length;
for (i = 0; i < filesAmount; i++) {
var reader = new FileReader();
reader.onload = function(event) {
$($.parseHTML('<img class="thumb" id="'+id+'">')).attr('src', event.target.result).appendTo(p);
id++;
}
reader.readAsDataURL(input.files[i]);
}
}
};
PHP code for uploading files:
$total = count($_FILES['files']['name']);
// Loop through each file
for($i=0; $i<$total; $i++) {
//Get the temp file path
$tmpFilePath = $_FILES['files']['tmp_name'][$i];
//Make sure we have a filepath
if ($tmpFilePath != ""){
//Setup our new file path
$newFilePath = "gig_pics/" . $_FILES['files']['name'][$i];
//Upload the file into the temp dir
move_uploaded_file($tmpFilePath, $newFilePath);
$file_sql = "INSERT INTO `gig_pics`(id,gig_id,pic) VALUES ('','$gid','$newFilePath')";
$file_res = mysqli_query($conn,$file_sql);
}
}
And after adding the name with jquery, I tried accessing the image as post
$main_img_path = $_POST['selectImage'];
$main_img_path = $_FILES['selectImage'];
But I could do anything.
I think your problem lies in the way you are selecting the specific file from the list of files:
$main_img_path = $_FILES['selectImage'];
I've not used PHP in a while, but in my opinion if you are already looping through the files on the server, why not check for the main image while looping? Something like this (assuming $_POST['selectImage'] contains the temp file name of the selected image):
$total = count($_FILES['files']['name']);
// Loop through each file
for($i=0; $i<$total; $i++) {
//Get the temp file path
$tmpFilePath = $_FILES['files']['tmp_name'][$i];
//Make sure we have a filepath
if ($tmpFilePath != ""){
if ($tmpFilePath === $_POST['selectImage']) {
// This is the selected image
}
//Setup our new file path
$newFilePath = "gig_pics/" . $_FILES['files']['name'][$i];
//Upload the file into the temp dir
move_uploaded_file($tmpFilePath, $newFilePath);
$file_sql = "INSERT INTO `gig_pics`(id,gig_id,pic) VALUES ('','$gid','$newFilePath')";
$file_res = mysqli_query($conn,$file_sql);
}
}
Like I said, this depends on what $_POST['selectImage'] contains as I'm not sure what you are storing there.

How to save canvas image data using php and ajax?

I followed this tutorial on my vps: http://permadi.com/2010/10/html5-saving-canvas-image-data-using-php-and-ajax/
testSave.php
<?php
if (isset($GLOBALS["HTTP_RAW_POST_DATA"]))
{
// Get the data
$imageData=$GLOBALS['HTTP_RAW_POST_DATA'];
// Remove the headers (data:,) part.
// A real application should use them according to needs such as to check image type
$filteredData=substr($imageData, strpos($imageData, ",")+1);
// Need to decode before saving since the data we received is already base64 encoded
$unencodedData=base64_decode($filteredData);
//echo "unencodedData".$unencodedData;
$randnum = rand(1111111111,9999999999);
// Save file. This example uses a hard coded filename for testing,
// but a real application can specify filename in POST variable
$tmpfname = tempnam("http://123.xx.xx.xx/test/tmp/", "FOO");
$fp = fopen(http://123.xx.xx.xx/test/test . uniqid() .".png","wb");
fwrite( $fp, $unencodedData);
fclose( $fp );
}
?>
JS
function saveViaAJAX()
{
var testCanvas = document.getElementById("testCanvas");
var canvasData = testCanvas.toDataURL("image/png");
var postData = "canvasData="+canvasData;
var debugConsole= document.getElementById("debugConsole");
debugConsole.value=canvasData;
//alert("canvasData ="+canvasData );
var ajax = new XMLHttpRequest();
ajax.open("POST",'testSave.php',true);
ajax.setRequestHeader('Content-Type', 'canvas/upload');
//ajax.setRequestHeader('Content-TypeLength', postData.length);
ajax.onreadystatechange=function()
{
if (ajax.readyState == 4)
{
//alert(ajax.responseText);
// Write out the filename.
document.getElementById("debugFilenameConsole").innerHTML="Saved as<br><a target='_blank' href='"+ajax.responseText+"'>"+ajax.responseText+"</a><br>Reload this page to generate new image or click the filename to open the image file.";
}
}
ajax.send(postData);
}
The problem is that when the user clicks 'send via ajax', there is no image sent/generated in the server directory(http://prntscr.com/8bhmxa). This is the outcome: http://prntscr.com/8bhi62 and everything in the directory remains unchanged.
What should happen is for a link of the image to be generated under the 'Saved as'
Any solutions?
P.S.
Is there anyway to echo the image link with php?
The problem is with your AJAX. Refer Url here the code is given for saving canvas with php and ajax.
Link

AJAX jQuery Avatar Uploading

I've been trying to find a very basic AJAX jQuery Avatar Uploading that I can use for my "settings" page so users can upload an avatar and unfortunately I can't find any.
This is my "function" so far for uploading the avatar
function uploadAvatar(){
$('#avatarDialog').fadeIn();
$('#avatarDialog').html("Logging in, please wait....");
dataString = $('#avatarForm').serialize();
var postURL = $('#avatarForm').attr("action");
$.ajax({
type: "POST",
url: site_url+"/libraries/ajax/image-upload.php",
data:dataString,
dataType:"json",
cache:false,
success:function(data){
if(data.err){
$('#avatarDialog').fadeIn();
$('#avatarDialog').html(data.err);
}else if(data.msg){
$('#avatarDialog').fadeIn();
$('#avatarDialog').html(data.msg);
var delay = 2000;
window.setTimeout(function(){
location.reload(true);
}, delay);
}
}
});
return false;
};
For my HTML/Input is this.
<form id="avatar_form" action enctype="multipart/form-data" method="post">
<input name="image_file" id="imageInput" type="file" />
<input type="submit" id="submit-btn" onClick="uploadAvatar();" value="Upload" />
And finally this is my PHP code (I have nothing here)
$thumb_square_size = 200;
$max_image_size = 500;
$thumb_prefix = "thumb_";
$destination_folder = './data/avatars/';
$jpeg_quality = 90; //jpeg quality
$return_json = array();
if($err==""){ $return_json['msg'] = $msg; }
else{ $return_json['err'] = $err; }
echo json_encode($return_json);
exit;
So how do I start this really. I just don't know where to start, I don't know exactly what to do.
Bulletproof is a nice PHP image upload class which encorporates common security concerns and practices, so we will use it here as it also makes the whole process much simpler and cleaner. You will want to read the approved answer on this question here (https://security.stackexchange.com/questions/32852/risks-of-a-php-image-upload-form) to better understand the risks of accepting file uploads from users.
The PHP below is really basic and really only handle the image upload. You would want to save the path or the file name that was generated in a database or in some kind of storage if the image is uploaded successfully.
You may also want to change the directory in which the image is uploaded to. To do this, change the parameter for ->uploadDir("uploads") to some other relative or absolute path. This value "uploads" will upload the image to the libraries/ajax/uploads directory. If the directory does not exist, bulletproof will first create it.
You will need to download bulletproof (https://github.com/samayo/bulletproof) and make sure to upload or place it in libraries/bulletproof/. When you download the class from github it will be in a ZIP archive. Extract the zip archive and rename bulletproof-master director to just plain bulletproof. Place that directory in the libraries directory.
HTML
<form id="avatar_form" action enctype="multipart/form-data" method="post">
<input name="image_file" id="imageInput" type="file" />
<input type="submit" id="submit-btn" value="Upload" />
</form>
JS
$('#avatar_form').submit(function( event ){
event.preventDefault();
var formData = new FormData($(this)[0]); //use form data, not serialized string
$('#avatarDialog').fadeIn();
$('#avatarDialog').html("Logging in, please wait....");
$.ajax({
type: "POST",
url: site_url + "/libraries/ajax/image-upload.php",
data: formData,
cache: false,
contentType: false,
processData: false,
success: function(data){
if(data.code != 200){ //response code other than 200, error
$('#avatarDialog').fadeIn();
$('#avatarDialog').html(data.msg);
} else { // response code was 200, everything is OK
$('#avatarDialog').fadeIn();
$('#avatarDialog').html(data.msg);
var delay = 2000;
window.setTimeout(function(){
location.reload(true);
}, delay);
}
}
});
return false;
});
PHP
//bulletproof image uploads
//https://github.com/samayo/bulletproof
require_once('../bulletproof/src/bulletproof.php');
$bulletproof = new ImageUploader\BulletProof;
//our default json response
$json = array('code' => 200, 'msg' => "Avatar uploaded!");
//if a file was submitted
if($_FILES)
{
try
{
//rename the file to some unique
//md5 hash value of current timestamp and a random number between 0 & 1000
$filename = md5(time() . rand(0, 1000));
$result = $bulletproof->fileTypes(["png", "jpeg"]) //only accept png/jpeg image types
->uploadDir("uploads") //create folder 'pics' if it does not exist.
->limitSize(["min" => 1000, "max" => 300000]) //limit image size (in bytes) .01mb - 3.0mb
->shrink(["height" => 96, "width" => 96]) //limit image dimensions
->upload($_FILES['image_file'], $filename); // upload to folder 'pics'
//maybe save the filename and other information to a database at this point
//print the json output
print_r(json_encode($json));
}
catch(Exception $e)
{
$json['code'] = 500;
$json['msg'] = $e->getMessage();
print_r(json_encode($json));
}
}
else
{
//no file was submitted
//send back a 500 error code and a error message
$json['code'] = 500;
$json['msg'] = "You must select a file";
print_r(json_encode($json));
}
Bulletproof will throw an exception if the image does not pass the validation tests. We catch the exception in the try catch block and return the error message back to the JavaScript in the JSON return.
The rest of the code is commented pretty well from the Bulletproof github page etc, but comment if anything is not clear.

Trying to upload images without refreshing page with javascript, not working

I am trying to upload images to my server via an html-form without refreshing the page. My problem is the files arent getting uploaded and I cant figure out why.
Javascript code:
function uploadFiles(event) {
var fileSelect = document.getElementById('file');
var files = fileSelect.files;
var formData = new FormData();
for (var i = 0; i < files.length; i++) {
var file = files[i];
if (!file.type.match('image.*')) {
alert("File: " + file.name + " is not an image and will not be uploaded.");
continue;
}
formData.append('images[]', file, file.name);
}
var xhr = new XMLHttpRequest();
xhr.open('POST', '../htdocs/Php/upload_file.php', true);
xhr.onload = function () {
if (xhr.status === 200) {
// File(s) uploaded.
alert('files uploaded');
} else {
alert('An error occurred!');
}
};
xhr.send(formData);
}
HTML code:
<form action="../htdocs/Php/upload_file.php" method="post" enctype="multipart/form-data">
<input type="file" name="images[]" id="file" onchange="uploadFiles()" multiple required />
</form>
PHP code:
$numberOfFiles = count($_FILES['images']['name']);
for($id = 0; $id < $numberOfFiles; $id++)
{
if (!file_exists("../UploadedImages/" . $_FILES["images"]["name"][$id])) {
move_uploaded_file($_FILES["images"]["name"][$id], "../UploadedImages/" . $_FILES["images"]["name"][$id]);
}
}
Looks like your JavaScript is correct, but your PHP needs some attention. I modified your php so that it first check to see if $_FILES were passed. Then where you had some incorrect logic was in your !file_exists() statement and how you move and check the file name.
To check if a file exists, and to move the file you need to use $_FILES['images']['tmp_name']. The 'name' attribute is just the name of the file uploaded, not the physical file uploaded to the browser.
To really test your code, use firebug and look at the console. It should return a line that you can expand and look at what was posted and what was returned.
Here is an example, the following code i gave you returns this:
C:\filepath\binaries\tmp\phpDB53.tmp Was Succesuflly uploaded
C:\filepath\binaries\tmp\phpDB54.tmp Was Succesuflly uploaded
C:\filepath\binaries\tmp\phpDB55.tmp Was Succesuflly uploaded
C:\filepath\binaries\tmp\phpDB56.tmp Was Succesuflly uploaded
NOTE: Double check that the files paths are absolutely correct. When checking firebug console, the php file will also return file errors as well, given that you have php error reporting on.
//Check if files were passed through to your ajax page
if(isset($_FILES)) {
$numberOfFiles = count($_FILES['images']['name']);
for($id = 0; $id < $numberOfFiles; $id++)
{
if (file_exists($_FILES["images"]["tmp_name"][$id])) {
move_uploaded_file($_FILES["images"]["tmp_name"][$id], $_FILES["images"]["name"][$id]);
echo $_FILES["images"]["tmp_name"][$id] . " Was Succesuflly uploaded \r\n ";
} else {
echo "file didnt exists " . $_FILES["images"]["tmp_name"][$id] . "\r\n ";
}
}
} else {
//No Files were passed through
echo "no files passed through";
}
exit();
Hopefully that answers your question.

Categories

Resources