RecorderJS uploading recorded blob via AJAX - ajax

I'm using Matt Diamond's recorder.js to navigate the HTML5 audio API, and feel this question probably has an apparent answer, but i'm unable to find any specific documentation.
Question: After recording a wav file, how can I send that wav to the server via ajax? Any suggestions???

If you have the blob you'll need to turn it into a url and run the url through an ajax call.
// might be nice to set up a boolean somewhere if you have a handler object
object = new Object();
object.sendToServer = true;
// You can create a callback and set it in the config object.
var config = {
callback : myCallback
}
// in the callback, send the blob to the server if you set the property to true
function myCallback(blob){
if( object.sendToServer ){
// create an object url
// Matt actually uses this line when he creates Recorder.forceDownload()
var url = (window.URL || window.webkitURL).createObjectURL(blob);
// create a new request and send it via the objectUrl
var request = new XMLHttpRequest();
request.open("GET", url, true);
request.responseType = "blob";
request.onload = function(){
// send the blob somewhere else or handle it here
// use request.response
}
request.send();
}
}
// very important! run the following exportWAV method to trigger the callback
rec.exportWAV();
Let me know if this works.. haven't tested it but it should work. Cheers!

#jeff Skee's answer really helped but I couldn't grasps it at first, so i made something simpler with this little javascript function.
Function parameters
#blob : Blob file to send to server
#url : server side code url e.g. upload.php
#name : File index to reference at the server side file array
jQuery ajax function
function sendToServer(blob,url,name='audio'){
var formData = new FormData();
formData.append(name,blob);
$.ajax({
url:url,
type:'post',
data: formData,
contentType:false,
processData:false,
cache:false,
success: function(data){
console.log(data);
}
}); }
Server side code (upload.php)
$input = $_FILES['audio']['tmp_name'];
$output = time().'.wav';
if(move_uploaded_file($input, $output))
exit('Audio file Uploaded');
/*Display the file array if upload failed*/
exit(print_r($_FILES));

I also spent many hours trying to achieve what you are trying to do here. I was able to successfully upload the audio blob data only after implementing a FileReader and calling readAsDataURL() to convert the blob to a data: URL representing the file's data (check out MDN FileReader). Also you must POST, not GET the FormData. Here's a scoped snippet of my working code. Enjoy!
function uploadAudioFromBlob(assetID, blob)
{
var reader = new FileReader();
// this is triggered once the blob is read and readAsDataURL returns
reader.onload = function (event)
{
var formData = new FormData();
formData.append('assetID', assetID);
formData.append('audio', event.target.result);
$.ajax({
type: 'POST'
, url: 'MyMvcController/MyUploadAudioMethod'
, data: formData
, processData: false
, contentType: false
, dataType: 'json'
, cache: false
, success: function (json)
{
if (json.Success)
{
// do successful audio upload stuff
}
else
{
// handle audio upload failure reported
// back from server (I have a json.Error.Msg)
}
}
, error: function (jqXHR, textStatus, errorThrown)
{
alert('Error! '+ textStatus + ' - ' + errorThrown + '\n\n' + jqXHR.responseText);
// handle audio upload failure
}
});
}
reader.readAsDataURL(blob);
}

Both solutions above use jQuery and $.ajax()
Here's a native XMLHttpRequest solution. Just run this code wherever you have access to the blob element:
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("audio_data",blob, "filename");
xhr.open("POST","upload.php",true);
xhr.send(fd);
Server-side, upload.php is as simple as:
$input = $_FILES['audio_data']['tmp_name']; //temporary name that PHP gave to the uploaded file
$output = $_FILES['audio_data']['name'].".wav"; //letting the client control the filename is a rather bad idea
//move the file from temp name to local folder using $output name
move_uploaded_file($input, $output)
source | live demo

Related

Accept application/pdf in Ext.Ajax.request

I am using Ext.Ajax.request() to make an API call which produces MediaType.MULTIPART_FORM_DATA. This is being handled in the php layer which returns the object in
header("Content-Type: application/pdf");
echo $response;
The problem is, I am not able to handle the received object in the Ext.Ajax.request() since it always handles only Json objects by default.
I tried giving Headers, AcceptType in the request, but it always goes to the failure block.
Here is the code:
Ext.Ajax.useDefaultXhrHeader = false;
var responseText;
Ext.Ajax.request({
url: '/index.php/abc/xyz?value=' + value,
method: 'GET',
waitMsg: 'Printing Label',
contentType: 'application/octet-stream' //not sure,
responseType: 'blob' //not sure,
xhr2: false //not sure,
success: function (response) {
console.log("Success!!");
return "";
},
failure: function (response) {
//Always comes here. The API returns 200
console.log("Hi here in the error");
//Raw pdf gets printed
console.log(response.responseText);
}
});
but it always goes to the failure
For this you need to check in php side because may be something you have missed. I think may be this will help you readfile
Try with this code. Hope this will help/guide you to get required result.
Ext.Ajax.request({
url: '/index.php/abc/xyz?value=' + value,
method: 'GET',
waitMsg: 'Printing Label',
cors: true,
useDefaultXhrHeader: false,
withCredentials: true,
defaultHeaders: {
'Content-Type': 'application/octet-stream;'
},
timeout:0,//If don't know how time will take server to get the file then you can put 0. if you need
success: function(response) {
//In response you will directly get the octet-stream
//For showing pdf in front end side using blob url
var byteCharacters = atob(response.responseText),
len = byteCharacters.length,
byteNumbers = new Array(len),
key = 0,
byteArray,
blob,
contentType = 'application/pdf';
//insert charcter code in {byteNumbers}
for (; key < len; key++) {
byteNumbers[key] = byteCharacters.charCodeAt(key);
}
//convert {byteNumbers} into Uint8Array
byteArray = new Uint8Array(byteNumbers);
//create blob using {byteArray}
blob = new Blob([byteArray], {
type: contentType
});
// set {src} to {iframe}
window.open(window.URL.createObjectURL(blob), '_blank');
},
failure: function(response) {
//if somthing wrong in serverside then it will come in failure.
}
});
Hope this will also help you for this question as well.

Allow user to download a generated pdf file after uploading a file

I'm trying to allow a user to upload a 15 MB file to my web, from there that file should be posted to a web service of mine, receive the response (a pdf file) and serve that to the user so he can download it.
However, I'm ending in a URL like this with no prompt to download anything, just a 404 error: http://localhost:10080/Download?file=%PDF-1.4%%EF%BF%BD%EF%B (etc)
Some points:
First I will compress the file
Because of the previous point, I'm using Ajax to post the file
Ajax code
$("#file").on("change", function(evt) {
var files = evt.target.files;
/* Create zip file representation */
var zip = new JSZip();
/* Name, content */
zip.file("data.zip", files[0]);
zip.generateAsync({
compression: 'DEFLATE',
type: 'blob'
}).then(function(zc) { // Function called when the generation is complete
/* Create file object to upload */
var fileObj = new File([zc], "compressed-data");
/* form data oject */
var formData = new FormData();
/* $('#file')[0].files[0] */
formData.append('attachments', fileObj);
$.ajax({
type: "POST",
url: $("form#data").attr("action"),
data: formData,
contentType: false,
processData: false,
success: function (returnValue, textStatus, jqXHR ) {
window.location = '/Download?file=' + returnValue;
}
})
Python Web Code
def post(self):
attachments = self.request.POST.getall('attachments')
#handle the attachment
_attachments = [{'content': f.file.read(),
'filename': f.filename} for f in attachments]
# Use the App Engine Requests adapter. This makes sure that Requests uses
# URLFetch.
requests_toolbelt.adapters.appengine.monkeypatch()
#web service url
url = 'http://localhost:8080'
files = {'attachments': _attachments[0]["content"]}
resp = requests.post(url, files=files)
self.response.headers[b'Content-Type'] = b'application/pdf; charset=utf-8'
self.response.headers[b'Content-Disposition'] = b'attachment; filename=report.pdf'
self.response.out.write(resp.content)
Python Web Service Code
#app.route('/', methods=['POST'])
def hello():
#the attached ZIPPED raw data
f = request.files["attachments"]
#to unzip it
input_zip = ZipFile(f)
#unzip
data = [input_zip.read(name) for name in input_zip.namelist()]
generator = pdfGenerator(io.BytesIO(data[0]))
return generator.analyzeDocument()
The pdf generator uses Reportlab, writes the pdf over a
io.BytesIO() and returns it with output = self.buff.getvalue()
1.- What am I doing wrong with the window location thing?
2.- Am I doing something wrong with the file type?
I'm two days into this, now I need help.
Thanks.
However, I'm ending in a URL like this with no prompt to download anything, just a 404 error: http://localhost:10080/Download?file=%PDF-1.4%%EF%BF%BD%EF%B (etc)
That's what you're asking in window.location = '/Download?file=' + returnValue;, you redirect the user to /Download.
When you call your service, you should ask for a Blob response. Then, use saveAs (or FileSaver.js, a polyfill) to trigger the download.
As far as I know, $.ajax doesn't let you download binary content out of the box (it will try to decode your binary from UTF-8 and corrupt it). Either use a jQuery plugin (like jquery.binarytransport.js) or use a xhr directly.
$.ajax({
type: "POST",
url: $("form#data").attr("action"),
data: formData,
contentType: false,
processData: false,
dataType: 'binary', // using jquery.binarytransport.js
success: function (returnValue, textStatus, jqXHR ) {
// Default response type is blob
saveAs(returnValue, "result.pdf"); // using FileSaver.js
}
})

SummerNote onImageUpload converting server request to C# BASE64?

I have a C# MVC project where I will need to both use Summernote v0.8.2 as my WYSIWYG editor, along with exporting a PDF with jsPDF. I know that there are examples to make this work. My issue is that I need to custom resize/process the image that's inserted with summernote. Again, I know that you can capture this event using the onImageUpload callback. I'm having trouble correctly handing the incoming Request on the server to get the image and convert it into a BASE64 string. I would think this should be pretty easy, but I can't figure out what to do with the incoming Request to extract the Image. I've give you the whole process just to make sure you have enough info to help.
Here's my Summernote setup:
$('.summernote').summernote(
{
toolbar: [
['style', ['bold', 'italic', 'underline', 'clear']]
, ['fontname', ['fontname']]
, ['fontsize', ['fontsize']]
, ['color', ['color']]
, ['insert', ['picture']]
]
, callbacks: {
onImageUpload: function (image) {
uploadImage(image[0]);
}
}
}
);
Here's the AJAX call: FYI - I did change the data appended from image to file. Didn't change outcome.
function uploadImage(file, editor, welEditb) {
var data = new FormData();
//data.append("image", image);
data.append("file", file);
$.ajax({
url: '/home/UploadSummerNoteFile',
cache: false,
contentType: false,
processData: false,
data: data,
type: "post",
success: function (data) {
alert('display base64 data: ' + data);
//editor.insertImage(welEditable, url);
},
error: function (data) {
console.log(data);
}
});
}
My server method doesn't have any parameters, and I'm not sure how to extract just the FILE (IMAGE?) content. Once I get the actual file, I need to modify and change it (size, resolution, etc., which I can do), then convert it into BASE64 and send it back to the UI. So, my questions here this:
How do I get the file (image) from the request stream?
How do convert whatever this 'thing' is from above into BASE64?
I've used an online BASE64 converter for the image that I've been testing with so I know that my attempts haven't created a valid string.
Here's a partial example that I've found online, modified it (poorly) in an attempt to make work, which it doesn't:
byte[] buffer = new byte[Request.InputStream.Length];
Request.InputStream.Read(buffer, 0, buffer.Length);
string data = Encoding.Default.GetString(buffer);
string[] tokens = data.Split(',');
if (tokens.Length > 1)
{
// not sure what I'm doing, trying stuff. BOOOOM!
image = Convert.FromBase64String(tokens[1]);
base64 = Convert.ToBase64String(image);
//string fileName = DateTime.Now.ToString("yyyyMMddHHmmssffff") + ".png";
//string path = Path.Combine(#"D:\www\images", fileName);
//File.WriteAllBytes(path, image);
}
What do I need to do with the buffer or the data object? Where does the content of the file live in the request? Is it already converted when it was serialized for transport to the server? Also, assuming everything else gets completed, do I need to save the file to the server so it can be placed within Summernote's editor.insertImage(welEditable, url)? Thanks for your time and help!
Seems that I made this much harder than it needed to be. It's just a regular request, so extract the file from the request, and copy it to a memory stream. In this case I send back the BASE64 string to the calling function. Hopefully this helps others.
[HttpPost]
public JsonResult UploadFile()
{
var fileName = Request.Files[0].FileName;
var base64 = string.Empty;
using (var memoryStream = new MemoryStream())
{
Request.Files[0].InputStream.CopyTo(memoryStream);
var fileContent = memoryStream.ToArray();
base64 = Convert.ToBase64String(fileContent);
}
return Json(base64);
}
Here's the uploadImage ajax method changes: I create an instance of an IMG, and change the src to be the BASE64 value.
function uploadImage(file, editor, welEditb) {
var data = new FormData();
data.append("file", file);
$.ajax({
url: '/home/UploadSummerNoteFile',
cache: false,
contentType: false,
processData: false,
data: data,
type: "post",
success: function (data) {
var image = $('<img>').attr('src', 'data:' + file.type + ';base64,' + data);
$('.summernote').summernote("insertNode", image[0]);
},
error: function (data) {
console.log(data);
}
});
}

Ajax file upload to Parse Express JS get 500 server error for files more than 2 MB size

I am getting 500 internal server error issue when uploding file having size more than 2MB to parse.com through an ajax.The application is hosted on parse.com and written using Cloud code plus Express JS. Files (images+videos) used to be
uploaded without any problem but recently application is getting 500 error for big files. Files less than 1 MB are still uploaded successfully. Let me show the code.
1. Express JS controller to upload file (Server-Side)
Note1: Upload file is not send to url, https://api.parse.com/1/files/filename but to custom url created in
Express JS, https://example.com/file?name=filename
Note2: File data is send to custom Express JS url and the controller method "file", mention below, make use of Cloud Code Buffer Module to create parse file and send response back to client(Browser).
exports.file = function(req, res) {
var buf = new Buffer(req.body, 'base64');
var fileType = req.get("Content-Type");
var fileName = decodeURIComponent(common.trim(req.query.name));
var file = new Parse.File(fileName, {base64: buf.toString('base64')}, fileType);
file.save().then(function() {
res.json({url: file.url(), name: file.name()});
}, function(error) {
var message = "";
if(req.app.settings._gs.debug === true) {
message = error.code + ' - ' + error.message;
}
else {
message = 'Failed uploading file.';
}
res.json(message);
});
};
2. Jquery ajax method (Client-Side)
//file change handler
$('.upload').on('change', function(e) {
var files = e.target.files || e.dataTransfer.files;
uploadVideo(files[0]);
});
//Video upload handler
var uploadVideo = function(file) {
$.ajax({
async: false,
cache: false,
type: "POST",
dataType: 'json',
url: "https://example.com/file?name=fileNameWithExtension",
data: file, //file binary data
processData: false,
contentType: false,
beforeSend: function(jqXHR, settings) {
//set content type
jqXHR.setRequestHeader('Content-Type', file.type);
},
success: function(data, textStatus, jqXHR) {
//success callback
},
error: function(jqXHR, textStatus, exception) {
//error callback
}
});
}
Code working absolutely fine with file less than 1 MB but more than 1MB size gives 500 internal server error.
I had tried to debug the problem and i found an interesting thing, which is, the control never reaches to controller method, controller does not execute " exports.file = function(req, res) {....}" but breaks before at some point and send 500 error. There is no entry in parse.com log for an error. There is no way i can find the real problem which causes the 500 code. Any idea please ?
Found out the problem. Parse.com does not allow more than 1MB of post data.

Monitor AJAX JSON Object download/transfer progress

I would like to know if it is possible to create a progress bar for an AJAX call where data returned is a JSON Object which represents a large database . This functions is used to synchronize between a client - server side database, and would like to show progress for users, like a normal file download...
I have tried the following without sucesss..
$.ajax({
xhr: function() {
var xhr = new window.XMLHttpRequest();
xhr.addEventListener("progress", updateProgress, false);
function updateProgress (oEvent) {
if (oEvent.lengthComputable) {
var percentComplete = oEvent.loaded / oEvent.total * 100;
console.log(percentComplete);
} else {
console.log('Unable to compute Size');
}
}
return xhr;
},
type: "POST",
url: "http:s......"
ect....//
Probably using - XMLHttpRequest
I'm trying to achieve the same so digging it here.
Does this post work for you?

Resources