How to make documents upload using AJAX with progress Bar - php

I want to make an upload page for my site so that documents get uploaded asynchronously, I tried using AJAX, but AJAX has a limited access to the users filesystem, and when the information is sent to the server only the file name appears without the directory, I would like suggestion on how to do this easily without using JQuery, and also I would like to know if there is a way to monitor the progress of a file upload, so that I could add a progress bar to my site.
function createXMLHttpRequestObject(){
var xmlHttp = 3;
if(window.ActiveXObject){
try{
//test for new version of internet Explorer
xmlHttp = new ActiveXObject("Msxml.XMLHTTP");
}
catch(e){
try{
xmlHttp = new ActiveXObject("Microsoft.XMLHTTP");
}
catch(e){
xmlHttp = 2;
}
}
}
else{
try{
xmlHttp = new XMLHttpRequest();
}
catch(e){
xmlHttp = 1;
}
}
if(!xmlHttp){
alert("Error creating Objece");
}
else{
var xHttpArr = new Array();
xHttpArr.push(xmlHttp);
var i = xHttpArr.length - 1;
return xHttpArr[i];
}
}
function process(xmlHttp, i){
if(xmlHttp.readyState == 4 || xmlHttp.readyState == 0){
//value = encodeURIComponent( objRef.value );
xmlHttp.open("GET", "php/AjaxBody.php?value="+i, true);
xmlHttp.onreadystatechange = handleServerResponse;
xmlHttp.send(null);
}
else{
alert("Hold on");
}
}
function handleServerResponse(){
if(test.readyState == 1 || test.readyState == 2 || test.readyState == 3){
}
if (test.readyState == 4){
if(test.status == 200){
txtResponse = test.responseText;
bodyDiv = document.getElementById("body");
bodyDiv.innerHTML = txtResponse;
}
else{
alert("Error with the xmlHttp status");
}
}
/*
else{
alert("Error with the xmlHttp readystate: " + x.status);
} */
}
Above is the code that creates the Object
button.onclick = function() {
send = createXMLHttpRequestObject();
frmUpload = document.getElementById("frmUpload");
file = document.getElementById("fileUpload");
processSending(send, frmUpload);
}
Above when the process method is called to send the file,
on the server I try to echo the file path, only the the name appears, like this
<?php
echo $_GET['value'];
?>

First of all you are doing your file upload wrong. File uploads require you to do a proper POST request using forms as it requires the enctype form attribute to be multipart/form-data. Why? The browser sends the binary file data through the POST request and does the hard work of encoding the data correctly through the POST request to be read on the server. Any other way and you will just be getting the file name at the server (you can verify this with a tool like Fiddler).
Alright, then how do you do a file upload using AJAX? AFAIK it's not possible to read the user's file system directly (I think FileReader only allows reading through the sandboxed file system through the browser but I may be wrong here), so IMO there are 2 ways to go here:
Using a hidden iframe approach for the file upload. Google it you will find lots of info it.
Use a Flash based uploader. More on this at the end.
As far as getting the location of the file on the users file system using Javascript goes, forget about it. It's considered a security concern and many browsers only return the file name on reading the element value when using the HTML input file tag. (Unless you are thinking of using a flash component. More on that in the last point.)
Now coming to the progress bar issue. When your PHP script is actually run the entire file has already been uploaded to the server. So how to show a progress bar? A few (hackish) ways:
An old school approach is to create a CGI script on the server to handle the upload. The advantage? CGI scripts can be run during the upload allowing you to retrieve the actual byte level progress of the upload. But this also requires you to update the progress at some place on the server which you can poll (with a separate AJAX request) and show in the browser to the user.
Another most commonly used approach is using a flash based uploader (please don't kill me StackOverflow community). Yes it's still used by big names (I am looking at you Facebook). The advantage you will have is that you don't need any special scripts on the server. The Flash based client is fully aware of the number of bytes uploaded. Also you may have access to the actual file path string (note the use of may and string) which is not so openly possible with plain JS and HTML.

You could use a FileReader and read the file into an ArrayBuffer or a BinaryString and then use multiple requests to send for example 1 mb sized packages. The receiving php script would then have to 'rebuild' the file by appending each received part to it. This would also solve the problem of echoing the file path on the server as you can (and have to) decide where to save it before writing to it.

Related

Post web image to a server

I've read many posts that due to security risks you cannot upload to your server with an image from your folder as javascript isnt allowed such access. However, I have a situation where i have an svg image on a web site that I convert to a png whilst on the website. But, I wish to send the converted image to my server.
Will I encounter the same problems as if I were uploading from my documents?
I tried to make an example of jsfiddle but it seems it doesnt accept document.write very well, so here's sort of a work-around:
DEMO: jsfiddle
Ideally we would have a button defined as so:
<button id="image" onClick="image()">Convert & Send</button>
Then have the code that does the conversion within a function along with the ajax
function image() {
//conversion code & ajax
}
So in conclusion I would just like to know if this is possible if not, i would be grateful if you could show an alternative way, whether it may include a combination of php.
thanks in advance
It seems as though the fiddle isnt loading heres the snippet: of the conversion
function image () {
var svg = document.getElementById("svg-container").innerHTML.trim();
var canvas = document.getElementById('svg-canvas');
canvg(canvas, svg, { renderCallback: function () {
var img = canvas.toDataURL("image/png");
document.write('<img src="'+img+'"/>');
}
});
I'm not sure about what your question is, but indeed, you can use a combination of Ajax + PHP to upload your image.
The client would POST an encoded image (e.g. encoded in Base64) using ajax (using jQuery.post, for example), while the PHP would receive the image and store it (after decoding it) in your server.
For an example of the process, check this question, where a specific case of a canvas is discussed. I think your SVG conversion could work in a similar way.
PS: For some reason, I couldn't load your Fiddle.
EDIT:
So both Ajax & PHP are written on the front end to send the image to
my server/database (ruby on rails). Is that correct?
No. Only Javascript (with Ajax) is used in the client. PHP would be the server part of the process, so in your case it would not be used as you are already using Ruby on Rails. In other words:
The client (browser) uses Javascript (maybe JQuery) to POST the image data (in your snippet, img) to the server (more info here).
The server (a PHP, ASPX or Ruby script [among others]) gets the POSTed data and saves the picture on disk (some info here).
If you can use PHP (in the server) for the specific process of saving the image, you can use the question I linked before as a guide.
Yes Of Course Their are ways:
I know 2:
1-(This One I know it works on chrome and Firefox but don't know IE):
First Get The Base 64 Data Of An Image In Canvas:
<canvas id="Canv" ....(Other Attributes)>
Your Browser does not support the canvas element :(
</canvas>
<button type="button" OnClick="Image()">Transform and Save</button>
<script type="text/javascript>
var can =document.getElementById('Can');
var ctx = can.getContext("2d");
//do something with ctx
function image(){
//You Should check the real format using img.src
var data = can.toDataURL("image/png");
var array = data.split(".");
var Base64Data = array[1];
//Now step 2 :Sent it to PHP
//Check for Browser compatibly
var ajx = new XmlHttpRequest()
ajx.onreadystatechange=function()
{
if (ajx.readyState==4 && ajx.status==200)
{
if(ajx.ResponseText == "Err"){//if the paged returned error
alert("An error Has Occurred");
return;
}//if not
alert("Saved Succesufuly");
}
}
ajx.open("GET","Save.php?q=" + Base64Data , true);
}
</script>
Step3: Interprete it With PHP
<?PHP
if(isset($_GET['q] And !Empty($_GET['q'])){
try {
$Data = $_GET['q'];
$hndl = fopen("Saved/Pic1.jpg" , "w");
fwrite($hndl , $Data);
fclose($hndl);
}catch(Exception $err){
echo "Err";
}
}else {
echo "Err";
}
?>
Yeap And That it.:D
You Could also loop throught each file in that directory and create a load button that get the Base64 Value And the first stuffs and out it into canvas using pucontent method of canvas element object

Saving WAV File Recorded in Chrome to Server

I've seen many partial answers to this here and elsewhere, but I am very much a novice coder and am hoping for a thorough solution. I have been able to set up recording audio from a laptop mic in Chrome Canary (v. 29.x) and can, using recorder.js, relatively easily set up recording a .wav file and saving that locally, a la:
http://webaudiodemos.appspot.com/AudioRecorder/index.html
But I need to be able to save the file onto a Linux server I have running. It's the actual sending of the blob recorded data to the server and saving it out as a .wav file that's catching me up. I don't have the requisite PHP and/or AJAX knowledge about how to save the blob to a URL and to deal, as I have been given to understand, with binaries on Linux that make saving that .wav file challenging indeed. I'd greatly welcome any pointers in the right direction.
Client side JavaScript function to upload the WAV blob:
function upload(blob) {
var xhr=new XMLHttpRequest();
xhr.onload=function(e) {
if(this.readyState === 4) {
console.log("Server returned: ",e.target.responseText);
}
};
var fd=new FormData();
fd.append("that_random_filename.wav",blob);
xhr.open("POST","<url>",true);
xhr.send(fd);
}
PHP file upload_wav.php:
<?php
// get the temporary name that PHP gave to the uploaded file
$tmp_filename=$_FILES["that_random_filename.wav"]["tmp_name"];
// rename the temporary file (because PHP deletes the file as soon as it's done with it)
rename($tmp_filename,"/tmp/uploaded_audio.wav");
?>
after which you can play the file /tmp/uploaded_audio.wav.
But remember! /tmp/uploaded_audio.wav was created by the user www-data, and (by PHP default) is not readable by the user. To automate adding the appropriate permissions, append the line
chmod("/tmp/uploaded_audio.wav",0755);
to the end of the PHP (before the PHP end tag ?>).
Hope this helps.
Easiest way, if you just want to hack that code, is go in to recorderWorker.js, and hack the exportWAV() function to something like this:
function exportWAV(type){
var bufferL = mergeBuffers(recBuffersL, recLength);
var bufferR = mergeBuffers(recBuffersR, recLength);
var interleaved = interleave(bufferL, bufferR);
var dataview = encodeWAV(interleaved);
var audioBlob = new Blob([dataview], { type: type });
var xhr=new XMLHttpRequest();
xhr.onload=function(e) {
if(this.readyState === 4) {
console.log("Server returned: ",e.target.responseText);
}
};
var fd=new FormData();
fd.append("that_random_filename.wav",audioBlob);
xhr.open("POST","<url>",true);
xhr.send(fd);
}
Then that method will save to server from inside the worker thread, rather than pushing it back to the main thread. (The complex Worker-based mechanism in RecorderJS is because a large encode should be done off-thread.)
Really, ideally, you'd just use a MediaRecorder today, and let it do the encoding, but that's a whole 'nother ball of wax.

Images generated by JavaScript Canvas API aren't viewable when saved?

Full code can also be found here: https://gist.github.com/1973726 (partially version on jsfiddle http://jsfiddle.net/VaEAJ/ obviously couldn't have php running with jsfiddle)
I initially wrote some code which took a canvas element and saved it as an image (see working code here: https://gist.github.com/1973283) and afterwards I updated it so it could process multiple canvas elements but the main difference now is that the image data is passed through to my PHP script via jQuery ajax method rather than via a hidden form field.
Problem is the images appear to be blank. They are about 200kb each when generated so they obviously have some content but when you preview the image nothing shows and when I try and open the image in Adobe Fireworks or another photo application I can't open the file.
The image data appears to be coming through to the server fine, but I'm really not sure why now when I write the image using base64_decode it would mean the images that are generated would no longer be viewable? The only thing I can think of is that maybe the posting of data via ajax isn't sending all the data through and so it's generating an image but it's not the full content and so the image is incomplete (hence why a photo application can't open it).
When checking the post data in Firebug it suggests that the limit has been reached? Not sure if that's what the problem is?
The problem was actually with sending data via XHR. I was using jQuery ajax method initially and then I swapped it out for my own ajax abstraction but the problem was still occuring until someone on twitter suggested I use FormData to pass the data to the server-side PHP. Sample is as follows... (full code can be seen here: https://gist.github.com/1973726)
// Can't use standard library AJAX methods (such as…)
// data: "imgdata=" + newCanvas.toDataURL()
// Not sure why it doesn't work as we're only abstracting an API over the top of the native XHR object?
// To make this work we need to use a proper FormData object (no data on browser support)
var formData = new FormData();
formData.append("imgdata", newCanvas.toDataURL());
var xhr = new XMLHttpRequest();
xhr.open("POST", "saveimage.php");
xhr.send(formData);
// Watch for when the state of the document gets updated
xhr.onreadystatechange = function(){
// Wait until the data is fully loaded, and make sure that the request hasn't already timed out
if (xhr.readyState == 4) {
// Check to see if the request was successful
if (checkHTTPSuccess(xhr)) {
// Execute the success callback
onSuccessfulImageProcessing(card, newCanvas, ctx, getHTTPData(xhr));
}
else {
throw new Error("checkHTTPSuccess failed = " + e);
}
xhr.onreadystatechange = null;
xhr = null;
}
};
```
If you are not having Cross Origin SECURITY_ERR's (which your Fiddle suffers from, but as long as your images are on the same server they will be fine), and you are getting some data so you are probably having problems with your PHP. From the PHP user notes, you have to replace the spaces with +'s to decode base64 that has been encoded with Javascript.
$data = str_replace(" ", "+", $_POST['imgdata']);
file_put_contents("generated.png", base64_decode($data));

How to upload a file and display its information

I want to build a web service that will process some files.
Here is what I want to do:
User uploads a file to the server using "upload form", the file is saved as a temporary file on the server-side
Server-side python script processes the temporary file and produces some statistics (for example, number of lines and words in the file)
The statistics are displayed near the "upload form"
The question here is: I would like the file to be processed in the background just after it is uploaded, and after it is done, .append() the produced results to the current view. I do not want to assign a script to <form action="processing_script.php">... because the user will be redirected to the processing_script.php after clicking the Upload button.
Any clues? Maybe some neat ajax call?
function ajaxRequest(){
var activexmodes=["Msxml2.XMLHTTP", "Microsoft.XMLHTTP"] //activeX versions to check for in IE
if (window.ActiveXObject){ //Test for support for ActiveXObject in IE first (as XMLHttpRequest in IE7 is broken)
for (var i=0; i<activexmodes.length; i++){
try{
return new ActiveXObject(activexmodes[i])
}
catch(e){
//suppress error
}
}
}
else if (window.XMLHttpRequest) // if Mozilla, Safari etc
return new XMLHttpRequest()
else
return false
}
function postFile(){
var mypostrequest=new ajaxRequest()
mypostrequest.onreadystatechange=function(){
if (mypostrequest.readyState==4){
if (mypostrequest.status==200 || window.location.href.indexOf("http")==-1){
document.getElementById("my_Result_tag").innerHTML=mypostrequest.responseText //this is where the results will be put!
}
else{
alert("An error has occured making the request")
}
}
}
var file = document.getElementById("my_file");
var parameters="file="+file //i am not sure of this peice though
mypostrequest.open("POST", "basicform.php", true)
mypostrequest.setRequestHeader("Content-type", "application/x-www-form-urlencoded")
mypostrequest.send(parameters)
}
Yeah, you'll need ajax for that. Create the form as usual, then submit it using Ajax. Form handling can be done as usual.
If you google 'file upload Ajax' I'm sure you can find everything you need :)
yeah, i'd made second ajax request and run it with schedule (e.g. every 10 seconds). it will query the server if uploaded file is processed. the server may even do the file processing in external program. the php-script that accepts second ajax request checks some READY status and give client the answer YES/NO/FAILED. when client accepts YES answer it refirects user to the RESULTS PAGE. if it accepts NO, it alerts user the problem.

Is it possible with javascript to find file's last modified time?

Is it possible? Now, I have done live chat, where with jquery's help I connect to .php file and check last modified time and if it is not as before, I retrieve messages. If it were possible in javascript I probably would save a lot of resources.
Thanks.
It's definitely possible if the server is sending an accurate Last-Modified header for that particular file:
var getMTime = function(url, callback) {
var xhr = XMLHttpRequest();
xhr.open('HEAD', url, true); // use HEAD - we only need the headers
xhr.onreadystatechange = function() {
if (xhr.readyState === 4 && xhr.status === 200) {
var mtime = new Date(xhr.getResponseHeader('Last-Modified'));
if (mtime.toString() === 'Invalid Date') {
callback(); // dont want to return a bad date
} else {
callback(mtime);
}
}
}
xhr.send();
};
getMTime('url here', function(mtime) {
if (mtime) console.log('the mtime is:' + mtime.toISOString());
});
Short answer: there's no way but AJAX + a server-side script (in your case, jQuery + php)
Being a client-side script, javascript gets run on the client's computer, so if the file whose m-time you want to check is on the server, then you are correct to use AJAX and a server-side script. No other way will work.
If the file whose m-time you want to check is on the client's computer, then you're out of luck. Javascript is intentionally designed to be prevented from accessing the client's files. (It can only access cookies, which are on the client's computer, however, because the browser (not any javascript) loads those into its work environment.)
Maybe HTTP ETag headers could be used to check if the page has changed. The first response contains ETag and your client uses that for the following request. Your PHP server side code would then send 304 if the page has not been modified.
http://en.wikipedia.org/wiki/HTTP_ETag

Categories