I´m starting to customize/improve an old audio editor project. I can import audio tracks to my canvas VIA drag&drop from my computer. The thing is that I also would like to use audio tracks already stored in the server just clicking over a list of available tracks... instead of use the <input type="file"> tags. How can I read the server side files with a FileReader?Ajax perhaps? Thanks in advance.
This is the code for the file reader:
Player.prototype.loadFile = function(file, el) {
//console.log(file);
var reader = new FileReader,
fileTypes = ['audio/mpeg', 'audio/mp3', 'audio/wave', 'audio/wav'],
that = this;
if (fileTypes.indexOf(file.type) < 0) {
throw('Unsupported file format!');
}
reader.onloadend = function(e) {
if (e.target.readyState == FileReader.DONE) { // DONE == 2
$('.progress').children().width('100%');
var onsuccess = function(audioBuffer) {
$(el).trigger('Audiee:fileLoaded', [audioBuffer, file]);
},
onerror = function() {
// on error - show alert modal
var tpl = (_.template(AlertT))({
message: 'Error while loading the file ' + file.name + '.'
}),
$tpl = $(tpl);
$tpl.on('hide', function() { $tpl.remove() })
.modal(); // show the modal window
// hide the new track modal
$('#newTrackModal').modal('hide');
};
that.context.decodeAudioData(e.target.result, onsuccess, onerror);
}
};
// NOTE: Maybe move to different module...
reader.onprogress = function(e) {
if (e.lengthComputable) {
$progress = $('.progress', '#newTrackModal');
if ($progress.hasClass('hide'))
$progress.fadeIn('fast');
// show loading progress
var loaded = Math.floor(e.loaded / e.total * 100);
$progress.children().width(loaded + '%');
}
};
reader.readAsArrayBuffer(file);
};
return Player;
Thanks for the suggestion micronn, I managed to make a bypass without touch the original code. The code as follows is the following:
jQuery('.file_in_server').click(function()
{
var url=jQuery(this).attr('src');//Get the server path with the mp3/wav file
var filename = url.replace(/^.*[\\\/]/, '');
var path="http://localhost/test/audio/tracks/"+filename;
var file = new File([""], filename); //I need this hack because the original function recives a buffer as well as the file sent from the web form, so I need it to send at least the filename
var get_track = new XMLHttpRequest();
get_track.open('GET',path,true);
get_track.responseType="arraybuffer";
get_track.onload = function(e)
{
if (this.status == 200) //When OK
{
Audiee.Player.context.decodeAudioData(this.response,function(buffer){ //Process the audio toward a buffer
jQuery('#menu-view ul.nav').trigger('Audiee:fileLoaded', [buffer, file]); //Send the buffer & file hack to the loading function
},function(){
alert("Error opening file");
jQuery('#newTrackModal').modal('hide');
});
}
};
get_track.send();
});
After this, in the fileLoaded function, the track is added to the editor.
var name = 'Pista ' + Audiee.Collections.Tracks.getIndexCount();
track = new TrackM({buffer: audioBuffer, file: file, name: name}); //being audioBuffer my buffer, file the fake file and name the fake file name
Audiee.Collections.Tracks.add(track);
And... thats it!
Related
This is my first post, so be gentle! I'm a Rails beginner and clueless with JavaScript/JQuery...
I have a Rails project which requires that the user be able to select a file and be presented with a preview image, which they can then crop as they wish before uploading the cropped image asynchronously.
I have successfully implemented direct upload to S3 using the JQuery FileUpload plugin (following this tutorial) and I am able to present the user with a preview image which they can crop using Cropper.js. However I need help with the last step of uploading the cropped image.
Here is the JS I have so far for handling the image crop/upload to S3:
$(document).ready(function() {
$('.directUpload').find("input:file").each(function(i, elem) {
var fileInput = $(elem);
var form = $(fileInput.parents('form:first'));
var submitButton = form.find('input[type="submit"]');
var progressBar = $("<div class='bar'></div>");
var barContainer = $("<div class='progress'></div>").append(progressBar);
fileInput.after(barContainer);
fileInput.fileupload({
fileInput: fileInput,
url: form.data('url'), //read AWS config via form attributes
type: 'POST',
autoUpload: false, // prevent upload start on file selection
formData: form.data('form-data'),
paramName: 'file',
dataType: 'XML',
replaceFileInput: false,
The code above initializes JQuery FileUpload and passes my S3 configuration data.
Next I use the JQuery FileUpload's 'add' callback to display a preview image/cropbox, and to upload the image to S3 when the user clicks an 'Upload' button:
add: function (e, data) {
if (data.files && data.files[0]) {
var reader = new FileReader();
reader.onload = function(e) {
$('#preview_image').attr('src', e.target.result); // insert preview image
$('#preview_image').cropper() // initialize cropper on preview image
};
reader.readAsDataURL(data.files[0]);
};
$('#upload_image').on('click', function(){
$('#preview_image').cropper('getCroppedCanvas').toBlob(function (blob){
var croppedFile = new File([blob], 'cropped_file.png')
// How do I now get my cropped file data to upload instead of original file?
})
data.submit();
});
},
It is the last part, above, where I am now stuck - I've created a file from the cropped area, but have been unable to find a way to upload it instead of the original image.
The remaining code deals mainly with displaying upload progress and building an image URL that I can save to my database for image retrieval.
progressall: function (e, data) {
var progress = parseInt(data.loaded / data.total * 100, 10);
progressBar.css('width', progress + '%')
},
start: function (e) {
submitButton.prop('disabled', true); //disable submit button while image is loading
progressBar.
css('background', 'green').
css('display', 'block').
css('width', '0%').
text("Loading...");
},
done: function(e, data) {
submitButton.prop('disabled', false);
progressBar.text("Uploading done");
// extract key from S3 XML response and generate URL for image
var key = $(data.jqXHR.responseXML).find("Key").text();
var url = '//' + form.data('host') + '/' + key;
// create hidden field containing image URL, which can then be stored in model
var input = $("<input />", { type:'hidden', name: 'image_url[]', value: url })
form.append(input);
},
fail: function(e, data) {
submitButton.prop('disabled', false);
progressBar.
css("background", "red").
text("Failed");
}
});
This worked for me
var croppedFile = new File([blob], 'cropped_file.png');
data.files[0] = croppedFile;
data.originalFiles[0] = data.files[0];
or just
data.files[0] = new File([blob], 'cropped_file.png');
data.originalFiles[0] = data.files[0];
and then
data.submit()
I am having a problem with this code. i wanna process the cordova android image url ( ie. stored in localStorage ) to upload in my web server.
function processImages(list, i){
var images = list[i].images;
images && images.forEach(function(image, j){
window.resolveLocalFileSystemURI(image, function(entry) {
var reader = new FileReader();
reader.onloadend = function(evt) {
list[i].images[j] = evt.target.result;
}
reader.onerror = function(evt) {
alert("error");
}
entry.file(function(f) {
//alert("Image is added");
reader.readAsDataURL(f);
}, function(e) {
alert('Image process error : '+e);
});
});
});
}
This code runs good if i am enabling #alert("Image is added"); this alert.
without this alert the app is shutting down by giving error unfortunately appname has stopped.
Its also not working for n number of images of size more than 2mb.
Note : consider async call and image size is more than 2mb each minimum 10 image per record.
Please help me !!!
Thanks
I want to pass the input file from content page to extension background script, and then load it with FileReader() in the extension background script.
So in the web page I have a <input type="file"> and from onchange event I pass the file from content script to background page like this:
var myfile = document.getElementById('fileid').files[0];
chrome.runtime.sendMessage({myevent: "start", inputfile: myfile}, function(response) {});
in the background script I have this:
chrome.runtime.onMessage.addListener(function(message,sender,sendResponse){
if(message.myevent==="start")
{
var reader = new FileReader();
reader.onload = function(e) {
// file is loaded
}
reader.readAsArrayBuffer(message.inputfile);
}
});
but FileReader not load it, I'm not sure if this is correct way , but all i need is to pass the input file element to background script and load it with FileReader to send it with HTTP POST from background script. Please tell me what is wrong or how to do it correctly. It will help a lot if I see a sample code, because I'm new to chrome extension development, and not so experienced.
All messages send through the Chrome extension messaging API MUST be JSON-serializable.
If you want to get the contents of a file at the background page, you'd better create a (temporary) URL for the File object, pass this URL to the background page and use XMLHttpRequest to grab its contents:
// Create URL
var url = URL.createObjectURL(myfile);
// Pass URL to background page (ommited for brevity) and load it..
var x = new XMLHttpRequest();
x.onload = function() {
var result = x.response;
// TODO: Use [object ArrayBuffer]
};
x.open('GET', url); // <-- blob:-url created in content script
x.responseType = 'arraybuffer';
x.send();
Though why do you want to send the file to the background page? Content scripts can also send cross-origin requests.
This works for chrome. You could find the whole production code here.
https://github.com/Leslie-Wong-H/BoostPic/tree/7513b3b8d67fc6f57718dc8b9ff1d5646ad03c75/BoostPic_Chrome/js
main.js:
// Crossbrowser support for URL
const URLObj = window.URL || webkitURL;
// Creates a DOMString containing a URL representing the object given in the parameter
// namely the original Blob
const blobUrl = URLObj.createObjectURL(imageBlob);
console.log(blobUrl);
chrome.runtime.sendMessage(blobUrl, (res) => {
imgUrl = res;
console.log(imgUrl);
clearInterval(refreshIntervalId);
// To prevent that it happens to halt at " Image uploading ..."
setTimeout(() => {
var imgUrlText = document.querySelector(imgUrlTextBoxId);
imgUrlText.value = imgUrl;
}, 1000);
// double check to clear interval to prevent infinite error loop of LoadingStateOne
// Hope it works.
setTimeout(() => {
clearInterval(refreshIntervalId);
}, 500);
console.log("Stop uploading state message");
background.js:
chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
if (request.startsWith("blob")) {
console.log("RECEIVED");
getBase64Url(request).then((res) => {
console.log("Arrived here");
// Acquired from https://stackoverflow.com/questions/18650168/convert-blob-to-base64/18650249#
const reader = new FileReader();
reader.readAsDataURL(res);
reader.onloadend = function () {
const base64data = reader.result;
console.log(base64data);
here is my javaScript code:
window.addEventListener('load', function() {
var submitimages = document.getElementById('submitimages');
submitimages.addEventListener('click', upload);
var images = document.getElementById('images');
});
var upload = function(event) {
event.preventDefault();
event.stopPropagation();
var data = new FormData();
for(var i = 0; i < images.files.length; ++i) {
data.append('images[]', images.files[i]);
}
var xhr = XMLHttpRequest();
xhr.open('POST', 'upload.php?test=' + 'test', true);
xhr.send(data);
}
My objective is to upload multiple images using form data and I want those sent images to move on a different directory depending on text that is on the url upload.php?test=' + 'test' where as on my example I want to move those image to test folder
and here is my php code so far
Please help I tried everything I know but I think I need idea whos someone is more knowledgeable to JavaScript. Regards
We have an app that records audio, making use of the PhoneGap Media API and in iOS's case the File API.
When the user clicks the Accept & Upload button, the app moves that file to the server making use of PhoneGap's File.FileTransfer() method.
Works well with iOS, Android not so much.
When I connect my Android device to my computer and mount as a drive, I can see that the file is getting created at the root which is where it should be.
After the audio file has been created, I'm able to play the file on my device from the location stored in the global var fullRecordPath which = recording.wav
When I attempt to point File.FileTransfer() at that came path I'm getting Error Code = 1 which I understand is File Not Found
Code Handling the Accept & Upload tap event:
$('#btnAcceptUpload').live('tap',function () {
if(isIOS){
thisFileToUpload = fullRecordPath;
} else {
// thisFileToUpload = './'+fullRecordPath; //doesn't work
// thisFileToUpload = 'file:///'+fullRecordPath; //doesn't work
thisFileToUpload = fullRecordPath; //doesn't work
}
var options = new FileUploadOptions();
msg = '';
options.fileKey="file";
msg += "options.fileKey = "+options.fileKey+"\n";
options.fileName=thisFileToUpload.substr(thisFileToUpload.lastIndexOf('/')+1);
msg += "options.fileName = "+options.fileName+"\n";
options.mimeType='audio/wav';
options.chunkedMode = false;
msg += "options.mimeType = "+options.mimeType+"\n";
msg += "thisFileToUpload = "+thisFileToUpload;
alert(msg);
var ft = new FileTransfer();
ft.upload(thisFileToUpload, "http://10.0.17.121/~email/ttmovefiles.php", fileUploadSuccess, fileUploadFailure, options);
});
Success Callback:
function fileUploadSuccess(r) {
console.log("Code = " + r.responseCode);
console.log("Response = " + r.response);
console.log("Sent = " + r.bytesSent);
alert(r.response);
}
Failure Callback:
function fileUploadFailure(error){
alert("An error has occurred: Code = " + error.code);
}
Thanks for looking.
Alright, alright. I figured this one out. I promise I'll come back through and tighten this one down later, but wanted to get it documented so I might end helping another.
in iOS to create a new piece of media you have no choice, you gotta use the File api. This same fully qualified spot in the filesystem was moved in to the same global var which the Media.play() method played nicely with... in iOS.
Not sure why it works this way, but with Android, Media.play() doesn't like the fully qualified path passed in to it. It just wants the filename and it apparently searches from the root.
File.FileTransfer.upload() always wants the fully qualified path of the asset to upload, regardless iOS or Android.
To Make this work:
I used the File API to create the file that the audio Media then uses to move the recording in to. I set 2 global vars: one for playing the audio on the device fullRecordPath and the other for uploading fullUploadPath.
Here's the function the creates the file, invokes the media API and sets the global vars that Android wants:
window.requestFileSystem(LocalFileSystem.PERSISTENT, 0, function(fileSystem){
fileSystem.root.getFile(recordFileName, {
create: true,
exclusive: false
}, function(fileEntry){
alert("---------> Android File " + recordFileName + " created at " + fileEntry.fullPath);
fullRecordPath = recordFileName;
fullUploadPath = fileEntry.fullPath;
mediaVar = new Media(recordFileName, function(){
alert("Android media created successfully");
}, androidMediaCreateFailure, mediaStatusCallback); //of new Media
onMediaCreated();
}, androidMediaCreateFailure); //of getFile
}, androidMediaCreateFailure); //of requestFileSystem
Here's the code to play that media back
function playAudio() {
var my_media = new Media(fullRecordPath,
// success callback
function () {
console.log("playAudio():Audio Success");
},
// error callback
function (err) {
console.log("playAudio():Audio Error: " + err.code);
exposeObject(err);
});
my_media.play();
}
Here's the code to upload
$('#btnAcceptUpload').live('tap',function () {
if(isIOS){
thisfullUploadPath = fullRecordPath;
} else {
thisfullUploadPath = fullUploadPath;
}
var options = new FileUploadOptions();
msg = '';
options.fileKey="file";
msg += "options.fileKey = "+options.fileKey+"\n";
options.fileName=thisfullUploadPath.substr(thisfullUploadPath.lastIndexOf('/')+1);
msg += "options.fileName = "+options.fileName+"\n";
options.mimeType='audio/wav';
options.chunkedMode = false;
msg += "options.mimeType = "+options.mimeType+"\n";
msg += "thisfullUploadPath = "+thisfullUploadPath;
alert(msg);
var ft = new FileTransfer();
ft.upload(thisfullUploadPath, "http://10.0.17.121/~email/ttmovefiles.php", fileUploadSuccess, fileUploadFailure, options);
});
On android you need to resolveFileSystem
window.resolveLocalFileSystemURI(FILEURI, function(msg){
// success call msg.fullPath
}, function(){
// FAIL
});