What I'm trying to accomplish
[x] 1) User fills out form
[x] 2) User adds images to form through "drag & drop (html5)" or by "click to choose images"
and a preview is displayed on the page. (done)
Here it's easy to add code to trigger an upload of theese images to the server but I don't want that just yet.
[x] 3) Users clicks "add me & my desk" --> Create user account if doesn't already exist
[x] 4) Desk is added, and a connection to the right user is added as well.
[x] 5) Create a folder with the same name (id) as the desk_id.
::::THE QUESTION::::
6) -->> now I want to upload those dragged and dropped, or selected images to that folder.
:::::::::::::::::::
I've gotten this far with the information I found here: http://www.html5rocks.com/en/tutorials/file/dndfiles/ (the actual page really rocks!9
I know about this awesome solution: http://blueimp.github.com/jQuery-File-Upload/
But it's overkill for what I'm trying to do, and I happen to be so proud that I've got everything else working, and I really do think I'm so close.
words and expressions that keep coming up: read blob, check array blob, read from sandbox, canvas.toDataURL()
I feel that the answer is here: http://www.html5rocks.com/en/tutorials/file/xhr2/
AND / OR HERE http://www.html5rocks.com/en/tutorials/file/dndfiles/ Or HERE /
http://www.html5rocks.com/en/tutorials/file/filesystem/ (under "Duplicating user-selected files"), OR HERE http://robertnyman.com/2010/12/16/utilizing-the-html5-file-api-to-choose-upload-preview-and-see-progress-for-multiple-files/
You could say I'm at the next step after this: Preview an image before it is uploaded
but perhaps I could get a push in the right direction? :)
Of course I've had a look at these:
HTML5 Pre-resize images before uploading
facebook js api - HTML5 canvas upload as a photo
Currently displaying preview from DND files like this:
for (var i = 0, f; f = uppladdadeFiler[i]; i++) {
// Only process image files.
if (!f.type.match('image.*')) {
continue;
}
var reader = new FileReader();
// Closure to capture the file information.
reader.onload = (function(theFile) {
return function(e) {
// Render thumbnail.
var span = document.createElement('span');
span.innerHTML = ['<img class="thumb preview" src="', e.target.result,
'" title="', escape(theFile.name), '"/>'].join('');
document.getElementById('listImages').insertBefore(span, null);
var span2 = document.createElement('span');
span2.innerHTML = ['<img class="thumb inside" src="', e.target.result,
'" title="', escape(theFile.name), '"/>'].join('');
document.getElementById('huvudbilden').insertBefore(span2, null);
};
})(f);
$('#valdaBilder').show();
// Read in the image file as a data URL.
reader.readAsDataURL(f);
}
I will give you some inputs which I hope will lead you in the right direction. Please note that I am not providing an off-the-shelf working answer because of two reasons - 1. I am just too lazy:) and 2. from what I can see you are smart enough to figure it out once you get the gist of it... so here goes:
First thing to do is have a button named, say, 'Upload Files' and attach a fn to it like uploadFiles(). Now this function will look something like below:
function uploadFiles()
{
var file = files[0];
var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function()
{
if (xhr.readyState==4 && xhr.status==200)
alert(xhr.responseText);
};
xhr.open('POST', '/upload.php', true);
xhr.setRequestHeader('X-FILE-NAME', file.name);
xhr.send(file);
}
Ok, so the explanation:
var file = files[0];
The files object array should be something that you create in your drag and drop eventlistener functions, which will be file objects representing the files you dropped into the dropzone. Usually you create them so: files = event.dataTransfer.files; which creates a FileList object named files In the example I am only considering the first file in the dropzone - hence files[0]
I guess the rest of the code is pretty self-explanatory. One thing to note is:
xhr.setRequestHeader('X-FILE-NAME', file.name);
xhr.send(file);
As you can see we are sending out raw binary data content to the server. So the post operation is writing into the server stream with raw binary data of what the file contains. This is an important point because this affects how the server is able to read this posted data.
Server side upload.php:
I am just going to read the first 1000 bytes of the uploaded file and print it back into the client (which, based on the javascript code above, will alert it into the browser)
<?php
$streamHandle = fopen("php://input","rb");
$streamContent = fread($streamHandle,1000);
echo $streamContent;
?>
Many people get confused on how to read content at the server side and think about using $_POST, or $_FILES, but if you are sending data using X-FILE-NAME, then you have to read it by opening a handle to php://input which is the standard input stream of the running php process.
Once you have read the stream, it is only a matter of fwrite-ing it into a new file in whatever directory you want to.
Like I said, this is not a turn-key solution that you can just copy-paste into your particular code, but I hope this helps you in looking in the right direction for file uploads using HTML5's drag and drop and the file API provided by Javascript to support it.
Related
In javascript, I read the file data by binding the on-change method to the file input and saving the file data into another input using the following code
$("#release_cover_custom").on('change', function (evt) {
var files = evt.target.files; // FileList object
// Loop through the FileList and render image files as thumbnails.
for (var i = 0, f; f = files[i]; i++) {
// Only process image files.
if (!f.type.match('image.*')) {
continue;
}
var reader = new FileReader();
// Closure to capture the file information.
reader.onload = (function (theFile) {
return function (e) {
$("#release_cover_custom_data").val(e.target.result);
};
})(f);
// Read in the image file as a data URL.
reader.readAsDataURL(f);
}
});
why i use the above code?, to store the image data, because i have a form where i provide settings for the email template that would be sent later and there i have to provide the background image to be used inside the email, i need to preview the email with all the settings and along with the background image provided to upload before saving the form or uploading the image, so i read the image data, save it to an input and then open a modal window to preview email and post all the necessary variables there including the image data which is then used in the following way inside the css to apply the background-image like below in my php view file
background-image:url('" . $background_image . "') !important;
Now i want to do the achieve the same thing via php, means if i have the image saved to a path and i want to read the image data and use it in the same way i did using javascript to futher pass it to the css property,
i tried to use base64_encode(file_get_contents('path/to/file'))
but the encoding seems to be different for the image data, as the background image is not shown should i be using some other method to achieve it in php.
#quagaar reply (on the question) helped me solve the problem and replaced the following
$background_image=base64_encode(file_get_contents('/path/to/file'));
with
$background_image='data:image/png;base64,'.base64_encode(file_get_contents('/path/to/file'));
and everything works fine as expected.
EDIT:
between i was dealing with images only and if you are working with Images only and you need mime type (e.g. for headers, or like my case), then this is a fast and reliable technique:
$file = 'path/to/image.jpg';
$image_mime = image_type_to_mime_type(exif_imagetype($file));
It will output true image mime type even if you rename your image file.
I have an HTML form as such which consists of a input type=file.
<form method="post" id="xml-upload" enctype="multipart/form-data">
<input type="file" accept=".xml" required name="xml-selection-hidden" id="upload-btn">
</form>
(There is no submit button, submit is triggered via jQuery:)
$("input[type=file]#upload-btn").change(function(){
$("form#xml-upload").submit();
});
That's the easy part. Now, I am not quite knowledgeable in PHP file handling so the next part is harder for me. My idea of how these things work is that I make a PHP file and link to it in the action attribute of the form. For instance action="upload.php".
First of I need to check the file type, XML only (might allow TXT in the feature, but not of yet). A maximum size of the file of around 200kB ought to suffice. Simply using an embedded if-clause seems fine? (not tested)
if(($_FILES["file"]["type"]=="text/xml")) {
if ($_FILES["file"]["size"] < 200000) {
// run function
} else {
// error: max file size is 200kB
}
} else {
// error: only xml files are allowed
}
But now I'm stuck.
The goal is to manipulate the XML client-side. This is useful because I allow users to either choose the file upload option, or to give a direct XML input in a textarea. The server-side function (jQuery) for parsing the XML in the textarea is already finished, so it would be useful if I could use the same function to parse the XML that I get from the uploaded file.
I thought of two options:
1. The uploaded file is put in a temporary directory with a random name, I then run an ajax call with jQuery to the file. But how? How do I get jQuery to know where the file is stored?
2. Store the content of the uploaded file in localStorage and manipulate it accordingly. When a new file is uploaded, the older localStorage ought to be cleared of course.
The script that is run on the XML is something along these lines. Just so you know what happens with the XML input:
var xml = $("textarea#xml-input").val(),
xmlParsed = $.parseXML(xml),
xmlObject = $(xmlParsed);
$("#tree").html(output(xmlObject.find('node').first()));
function output(nodes) {
var newList = $("<ol>");
nodes.each(function (x, e) {
var newLI = $('<li> </li>');
for (var i = 0, l = e.attributes.length, a = null; i < l; i++) {
a = e.attributes[i];
newLI.attr("data-" + a.nodeName, a.value);
if (a.nodeName == "cat") {
newLI.html('' + a.value + '');
}
else if (a.nodeName == "word") {
newLI.html('' + a.value + '');
}
}
if ($(this).children('node').length) {
newLI.append(output($(this).children('node')));
}
newList.append(newLI);
});
return newList;
}
As I have said, I have tried my best in this post and gave it all I got, but I lack the knowledge. Looking for some help here. All help welcome!
For doing same as you wants you can create your own "xml_tmp" folder in your server root and then by using PHP move_uploaded_file() function to store your file in directory you selected for this and after storing current uploaded xml file you can ask via AJAX to get file name and path then send the requested info back to the client by using jQuery.parseXML() method you can read and manipulate your xml there.
I hope it help you!
Storing uploaded file by PHP:
move_uploaded_file($_FILES["file"]["tmp_name"], "xml_tmp/tmp.xml")
Imagine that 'xmlSrc' variable is the result of response from you AJAX call for requesting xml path and name
$.ajax({
type: "GET",
url: xmlSrc,
dataType: "xml",
success: function(xml) {
var xmlDoc = xml,
$xml = $( xmlDoc ),
$author = $xml.find( "author" );
// append the text from your parsed xml element to some HTML element
$( "#element" ).append( $author.text() );
}
});
1. The uploaded file is put in a temporary directory with a random name, I then run an ajax call with jQuery to the file. But how? How do I get jQuery to know where the file is stored?
jQuery has no interest in the temporary filename. The moment your PHP script has processed the upload request, the temporary file is deleted. That's on the server-side. jQuery is on client side.
So jQuery would get a filename of an inexistent file then.
You're perhaps looking for the browser file API which is able to access contents of a file without uploading it. Which seems fair as you're anyway dealing with a textbox if I understood your question right.
I'm having a problem finding if this is even possible (no info anywhere to be found).
Is it possible to EXTRACT a frame (thumbnail) during the video upload?
Extract using jscript is also an option if it's possible to extract user side.
Thanks for the help!
Fast forward almost five years since this question was posted, and the answer is now a yes!
Live demo
How to extract a frame during video upload using JavaScript
Before showing code, this is what we'll do:
Set an event handler on the input element that will take the video to be uploaded
When a file is selected from the file system, use the URL object to create a url to the local video file.
Load that URL into a video element.
When the video has loaded into memory, draw a frame on a canvas object.
Now export the frame rendered on the canvas into an image element (or optionally send that image to your server as a data url).
<input type="file" id="upload"/>
<img id="thumbnail"/>
<script>
var input = document.getElementById('upload');
var img = document.getElementById('thumbnail');
input.addEventListener('change', function(event){
var file = this.files[0];
var url = URL.createObjectURL(file);
var video = document.createElement('video');
video.src = url;
var snapshot = function(){
var canvas = document.createElement('canvas');
var ctx = canvas.getContext('2d');
ctx.drawImage(video, 0, 0, canvas.width, canvas.height);
img.src = canvas.toDataURL('image/png');
video.removeEventListener('canplay', snapshot);
};
video.addEventListener('canplay', snapshot);
});
</script>
I don't think there is a good way to do that in php. (https://stackoverflow.com/a/1309425/1488032)
If it is not just some webspace that you have rented but have the rights to install and run other software on the server I would suggest using something like ffmpeg and calling it from within php using system(), passthru() or exec() to extract what you want and do the rest of the processing in php again.
I'm running a browser game that relies on svg images embedded in xhtml but some browsers (especially mobile ones) don't support the full svg syntax. In this case I use such a system() call to do svg-to-png conversion using imagemagick's convert binary and display the result on my page.
system("echo '$svgString' | convert svg:- png:- | base64");
I suppose you have to fall back to something similar.
Here's some information on extracting frames using ffmpeg:
http://ubuntuforums.org/showthread.php?t=1141293
Javascript: no.
During upload: no.
Once you've uploaded, yes.
"Dev" provided the right link in the comments, but what you should do is save the video to your server and then run ffMpeg to grab the image. You can download ffMPEG here: http://ffmpeg.org/download.html (grab hte build you need if you're not confident on building it yourself - there are Linux and Windows builds).
The documentation is here: http://ffmpeg.org/ffmpeg.html but there is a slightly easier to read tutorial at http://linuxers.org/tutorial/how-extract-images-video-using-ffmpeg for grabbing an image.
Note: there is a PHP extension clled "phpFFMPEG" but I suggest you don't use it. Simply run the desired commands through "exec()" in PHP. Check for error return values as you can only run ffMPEG once per CPU core, so if you try it twice at the same time it might fail - either queue the actions or try again if it fails.
First, you need to select a program to extract the frame. ffmpeg is commonly used for this. Whatever you pick, it needs to be able to work with partial file contents.
php scripts dont start executing until after the entire file upload has completed, but php recently got a feature so that a different php script can be executed during the file upload, and will be able to get at uploading scripts data(the filename is the thing of interest to you).
http://php.net/manual/en/session.upload-progress.php
Then, basically call the external program to extract the frame from the monitoring script, using the temp file name being uploaded in the upload handling script.
to summarize:
upload the file to upload.php.
monitor.php will get the temp file name being uploaded in upload.php, and extract the frame.
Basically, I took rodrigo-silveira answer provided in this thread and modified it for my use and now the solution works like a charm. Even I was trying to upload the video thumbnail/poster of a video that a user wishes to upload and save the video and the thumbnail in a folder. Also, I didn't want to use ffmpeg.
Here is what I did: In the upload file called "upload.php" I have the following code with slight modification to rodrigo-silveira's solution above:
upload.php:
<input type="file" id="upload"/>
<img id="thumbnail"/>
<form action="action_page.php" method="post" target="_blank">
<input type="hidden" id="mytext" name="mytext" >
<input type="submit" value="Submit">
</form>
<script>
var input = document.getElementById('upload');
var img = document.getElementById('thumbnail');
input.addEventListener('change', function(event){
var file = this.files[0];
var url = URL.createObjectURL(file);
var video = document.createElement('video');
video.src = url;
var snapshot = function(){
var canvas = document.createElement('canvas');
var ctx = canvas.getContext('2d');
canvas.width = 350;
canvas.height = 250;
ctx.drawImage(video, 0, 0, canvas.width, canvas.height);
img.src = canvas.toDataURL('image/png');
document.getElementById("mytext").value = img.src;
video.removeEventListener('canplay', snapshot);
};
video.addEventListener('canplay', snapshot);
});
</script>
Both the HTML part and the JavaScript above are within the upload.php's body tag.
Now on to the action_page.php file:
<?php
$data = $_POST['mytext'];
$file = "photos/file".time().".png";
$uri = substr($data,strpos($data, ",") + 1);
file_put_contents($file, base64_decode($uri));
?>
Save both PHP files in the same folder and create another folder called "photos" in that folder. Your video thumbnail/poster image from a video that is selected in the upload.php page gets saved in the "photos" folder as png file. (Note: this solution does not upload the video, just the video thumbnail. But that is straight forward from here on.)
Using html5 javascript, how do you get the file path when user select the file?
I needed the file path to use in this example case:
user upload a file, pause it(I know so far I think only mozilla can do this), and then close the browser and plan to resume the file the next day. I need to know the file path for this file..
Even if you did have a path (some browsers used to give it to you), there is no way to set the path of a input of type file.
Therefore, it is not possible to do what you want with plain JS and the DOM.
I said it wasn't possible, but now that you asked I do think there is a way, with new File API. The following steps outline what needs to be done, but have in no way been tested, and I don't expect it to work, it's just to show you the way, also global variables are bad, it's just the simplest way to show you. Here's a good page with examples on using the File API http://www.html5rocks.com/en/tutorials/file/dndfiles/
First You need an input of type file, then you can use once a user selects a file, you are given access to the File object. http://dev.w3.org/2006/webapi/FileAPI/#dfn-filereader
<input type="file" id="files" name="files[]" multiple />
<script>
var fileBlobs = [];
function handleFileSelect(evt) {
var files = evt.target.files; // FileList object
// files is a FileList of File objects. You may now read their contents
var reader = new FileReader();
for (var i = 0, f; f = files[i]; i++) {
fileBlobs.push(reader.readAsBinaryString(f));
}
}
document.getElementById('files').addEventListener('change', handleFileSelect, false);
</script>
Second Now you have the content as a binary string. You can use the File API to store the file locally in a way that you can access later using the FileWriter and FileSaver interfaces http://dev.w3.org/2009/dap/file-system/file-writer.html
var bb = new BlobBuilder();
bb.appendfileBlobs.(fileBlobs[0]);
window.saveAs(bb.getBlob(), "test_file");
Third You need to make an Ajax request passing that blob to the server, tracking how much of the upload is complete. http://www.w3.org/TR/XMLHttpRequest/#the-upload-attribute. It doesn't look like tracking progress can be done on the client. Your may have to poll the server for actual progress. A possible solution to know where to start an interrupted upload is to have upload ids and when you restart an upload, you ask the server how much of the file has been uploaded.
Sorry I can't provide a full answer, but this is not an easy problem. The steps I gave you should take you in the right direction.
Much like you can't submit an HTTP request in pieces over several days, you can't do it with file uploads as well. The protocol just won't allow it. Hence the entire effort is futile.
As far as I know, that isn't possible as Javascript only has access to files that were shared with it through either a file input or drag-and-drop.
I want let user to upload images to server add some info (like description, tags) about each image.I use Uploadify to upload multiple images.
I wonder if it is possible to show thumbnails of the images (while the user enters the additional info about each image) before the images are actually uploaded to the server.
I want user to have the following experience:
Select multiple image files
Immediately after that enter additional information about each image while seeing images thumbnails
Press Upload Files button to upload images to server, and go to drink coffee...
I found this script, but I think it also uploads the file before displaying the image thumbnail.
I would appreciate any help !
If you could enforce an HTML 5 capable browser you could use the file-api
Example: http://html5demos.com/file-api
Sure it is possible. Use the FileReader object to get a data URL (or use File.url if you are sure the Client implements it.) and assign it to an new Image()object. Then you can insert the image into DOM.
As an alternative to the standard-based HTML5 APIs, you can use a plugin such as Flash or Browserplus.
There is actually a ready-made application which might do exactly what you want. It's called Plupload. You can upload your files / images using a variety of "runtimes", and do client-side image resizing before uploading. I guess you can hook a thumbnail preview somewhere in there, in certain runtimes.
Otherwise, you can try building what you want from scratch, using the HTML5 / Gears / BrowserPlus / etc. APIs.
I'm pretty sure flash and java can both do it. Flash would require certain (obvious) security precautions (ie, you can do this for any file, it must be selected by the user).
Meanwhile java would show a security popup.
Xavier posted this solution on another thread, and I tried to improove it to work with multiple file inputs. I hope it helps.
$("body").on('change', 'input:file', function(e){
for (var i = 0; i < e.originalEvent.srcElement.files.length; i++) {
var file = e.originalEvent.srcElement.files[i];
var img = document.createElement("img");
var reader = new FileReader();
reader.onloadend = function() {
img.src = reader.result;
}
img.width = "50";
reader.readAsDataURL(file);
if($(this).next().hasClass('image_place')){
$(this).next('.image_place').html('').append(img);
}else {
$(this).after('<div class="image_place"></div>');
$(this).next('.image_place').append(img);
}
}
});
It scans all file inputs in the document body and reads the image using the FileReader api. If it finds any images, it creates a div called "image_place" where he puts the image. If there's already a image inside, the script replaces the image.