Rails form submission by AJAX with an active storage attachment - javascript

I have a form that I want to submit using AJAX. The form lets you upload a picture as an attachment, among other fields. Now using pure rails it works just fine, and the AJAX post function I have set up also works...until I try to upload this image file. It just submits without the file as if I did not attach it. What is the correct flow for this? the ajax function
function postInstrument() {
$("form#new_instrument").submit(function(e) {
e.preventDefault();
$.ajax({
type: "POST",
url: `http://localhost:3000/users/${userId}/instruments`,
data: $(this).serialize(),
dataType: "json",
success: document.getElementById("new-instrument-form-div").innerHTML = 'Instrument Added!'
})
})
}

The solution was just to wrap my form in a FormData object.

You are using .serialize for your image data. And that is not possible.
This link is by far the best for you to read about file uploading https://developer.mozilla.org/en-US/docs/Web/API/File/Using_files_from_web_applications
function FileUpload(img, file) {
const reader = new FileReader();
this.ctrl = createThrobber(img);
const xhr = new XMLHttpRequest();
this.xhr = xhr;
const self = this;
this.xhr.upload.addEventListener("progress", function(e) {
if (e.lengthComputable) {
const percentage = Math.round((e.loaded * 100) / e.total);
self.ctrl.update(percentage);
}
}, false);
xhr.upload.addEventListener("load", function(e){
self.ctrl.update(100);
const canvas = self.ctrl.ctx.canvas;
canvas.parentNode.removeChild(canvas);
}, false);
xhr.open("POST", "http://demos.hacks.mozilla.org/paul/demos/resources/webservices/devnull.php");
xhr.overrideMimeType('text/plain; charset=x-user-defined-binary');
reader.onload = function(evt) {
xhr.send(evt.target.result);
};
reader.readAsBinaryString(file);
}
And here How can I upload files asynchronously?

Related

Javascript send image

In ajax I got it working but in javascript.
Ajax
// Get base64URL
var base64URL = canvas.toDataURL('image/jpeg').replace('image/jpeg', 'image/octet-stream');
AJAX request
$.ajax({
url: 'https://url/ajax.php',
type: 'post',
data: {image: base64URL},
success: function(data){
console.log('Upload successfully');
}
});
In JavaScript
var request = makeHttpObject();
request.open("POST", "https://url/ajax.php", true);
request.send(base64URL);
request.onreadystatechange = function() {
if (request.readyState==4 && request.status==200) {
console.debug(request.responseText);
} else {
console.debug(request.responseText);
}
};
JS uploads to server image with 0 kb.
Should it append in image file base64 ? That's why it is 0? Tried several things searching but still not working.

Submit <img> through jQuery ajax?

My page has a file input. When the user uploads a photo, they then crop it and the result is stored in an img element (using FileReader).
How can I submit this image through jQuery ajax?
EDIT
I got something working. There are 2 problems though. First, the image file size is really big (almost 1MB for a 600x600 picture).
Second, I am not sure how to verify in PHP that the file uploaded is an image.
$pic = $_POST['pic'];
$pic = str_replace('data:image/png;base64,', '', $pic);
$pic = str_replace(' ', '+', $pic);
$pic = base64_decode($pic);
$path = "c:/wwwroot/images/img.jpg";
file_put_contents($path,$pic);
Using ajax you could read file bytes using FileReader Convert it to base64 and then send it to server. This is how It goes:
var sendingcanvas = document.getElementById('sendingcanvas');
var dataURL = sendingcanvas.toDataURL("image/*");
var imagedatatosend = dataURL.replace(/^data:image\/(png|jpg);base64,/, "");
var formdata = new FormData();
formdata = {
'image': imagedatatosend
};
$.ajax({
url: 'serverside',
type: 'POST',
data: formdata,
encode: false,
cache:false,
success: function(data){}
});
Easy and Recommended Way:
function upload(file, servlet){
var xhr=new XMLHttpRequest(), sres=null;
xhr.onreadystatechange = function() {
if (xhr.readyState == XMLHttpRequest.DONE) {
alert(xhr.responseText);
sres=xhr.responseText;
}
}
xhr.open('post',servlet,false);
xhr.send(file);
return sres;
}
Call the function Inputing image location and serverside link And you are good to go :)
you question need more description but as for normal image image upload code is here:
$(document).on('submit', 'form', function (event) {
event.preventDefault();
var form_data = new FormData();
$($(this).prop('elements')).each(function () {
if (this.type == 'file')
form_data.append(this.name, this.files[0]);//here you can upload multiple image by iterating through files[]
else
form_data.append(this.name, $(this).val());// for text fields
});
$.ajax({
type: "POST",
cache: false,
contentType: false,
processData: false,
url: $(this).attr('action'),
data: form_data,
beforeSend: function () {
},
success: function (data) {
},
error: function (data) {
});
}
});
});
if (this.type == 'file')
form_data.append(this.name, this.files[0]);
this will add data from input type file data to form_data and then it will be send by ajax

SharePoint Online REST - Image upload via JavaScript/AJAX

I'm trying to upload an image to SharePoint using native JavaScript/jQuery - NOT SP.RequestExecutor.
I've cracked the authentication issue, nice and easy, so now it's just a case of working out how to upload binary files. If I put plain text in the file, it uploads fine, it's just binary data I'm having trouble with.
My code so far is included below. getToken() does it's thing and leaves me with a valid digest object to use. Also note I've blanked out the document library name with *'s.
function PerformUpload(fileName, fileData) {
getToken();
$.ajax({
url: siteFullUrl +
"/_api/web/GetFolderByServerRelativeUrl('/*****/')/Files" +
"/Add(url='" + fileName + "', overwrite=true)",
type: "POST",
async: false,
data: fileData,
processData: false,
contentType: "application/json;odata=verbose",
headers: {
"Accept": "application/json;odata=verbose",
"X-RequestDigest": digest
},
success: function (data) {
alert("Success");
},
error: function (err) {
alert("Error: \r\n" + JSON.stringify(err));
}
});
}
I've tried many combinations of different values for contentType, setting binaryStringRequestBody: true but the image is still corrupt when it comes into SharePoint.
My code at the moment to parse the file into binary is
var reader = new FileReader();
reader.onload = function (result) {
var fileName = '',
libraryName = '',
fileData = '';
var byteArray = new Uint8Array(result.target.result)
for (var i = 0; i < byteArray.byteLength; i++) {
fileData += String.fromCharCode(byteArray[i])
}
PerformUpload("image.jpg", fileData);
};
reader.readAsArrayBuffer(fileInput);
A file is being uploaded to SharePoint but if I try and view or download it it's corrupt.
Can anyone provide any guidance as to the correct way to upload a binary file to SharePoint? I should mention that if I replace (on the ajax call) data: fileData, with data: "A simple string", the file uploads and when I download it the contents of the file are A simple string.
If you are using SP.RequestExecutor to upload the file to SharePoint, you must be converted the ArrayBuffer into a string which can then be set as the body of a POST operation. See details here which guide you how to Upload file to SharePoint using REST by SP.RequestExecutor.
If you are using parsed file into binary with Jquery.Ajax, the image will corrupt when it comes into SharePoint. Also noted that the FileReader object accepts the file information for loading asynchronously. The onload and onerror events fire when the file is loaded successfully or fails. We should keep the proccess of onload event by default and get the result in onloadend event.
I tried the following articles and it work:
How to: Upload a file by using the REST API and jQuery
For simple, here is how I implemented:
var fileInput = jQuery('#getFile');
var file = fileInput[0].files[0];
var serverRelativeUrlToFolder = '*****'; //if the library in subsite, You have to remove the forward slash "/" before the document library relative url.
proccessUploadUsingJQueryAjax(file, serverRelativeUrlToFolder);
function getFileBuffer(file) {
var deferred = jQuery.Deferred();
var reader = new FileReader();
reader.onloadend = function (e) {
deferred.resolve(e.target.result);
}
reader.onerror = function (e) {
deferred.reject(e.target.error);
}
reader.readAsArrayBuffer(file);
return deferred.promise();
}
function addFileToFolderUsingJQueryAjax(fileName, arrayBuffer, serverRelativeUrlToFolder) {
// Construct the endpoint.
var fileCollectionEndpoint = String.format(
"{0}/_api/web/GetFolderByServerRelativeUrl('{1}')/files/add(overwrite=true, url='{2}')",
_spPageContextInfo.webAbsoluteUrl, serverRelativeUrlToFolder, fileName);
// Send the request and return the response.
// This call returns the SharePoint file.
return jQuery.ajax({
url: fileCollectionEndpoint,
type: "POST",
data: arrayBuffer,
processData: false,
contentType: "application/json;odata=verbose",
headers: {
"accept": "application/json;odata=verbose",
"X-RequestDigest": jQuery("#__REQUESTDIGEST").val()
}
});
}
function proccessUploadUsingJQueryAjax(file, serverRelativeUrlToFolder){
var getFile = getFileBuffer(file);
getFile.done(function (arrayBuffer) {
// Add the file to the SharePoint folder.
var addFile = addFileToFolderUsingJQueryAjax("image.jpg", arrayBuffer, serverRelativeUrlToFolder);
addFile.done(function (file, status, xhr) {
alert("File Uploaded");
});
addFile.fail(function (error) { alert("Error Add File: " + error.responseText); });
});
getFile.fail(function (error) { alert("Error Get File: " + error.responseText); });
}
Please let me know if it solved your problem.
Try adding this to your ajax settings
transformRequest: []
this will prevent Sharepoint from adding metadata to your file

How can I send the contents of a file to my server?

I'm trying to let users import an OPML file that I parse server (rails app) side. I'm having trouble as it seems that my server isn't getting the info (neither the success nor error functions run and even if I hardcode other data into the call, the call doesn't change).
Here's what I have embedded into the page:
<script>
function handleFileSelect(evt) {
var files = evt.target.files; // FileList object
// Loop through the FileList
for (var i = 0, f; f = files[i]; i++) {
var reader = new FileReader();
// Closure to capture the file information.
reader.onload = (function(theFile) {
return function(e) {
// Print the contents of the file
var span = document.createElement('span');
span.innerHTML = ['<p>',e.target.result,'</p>'].join('');
document.getElementById('list').insertBefore(span, null);
};
$.ajax({
type: 'GET',
url: "/parse_opml",
data: {file: f},
success: function(details, response) {
console.log('woo!');
},
error: function(data, response) {
console.log('boooo');
}
});
})(f);
// Read in the file
reader.readAsText(f);
}
}
document.getElementById('the_o').addEventListener('change', handleFileSelect, false);
</script>
<input id="the_o" name="files[]" type="file">
Looking at chrome's network panel, I'm seeing the call: Request URL:blob:http%3A//localhost%3A3000/14e2be6b-059f-47f5-ba37-97eda06242b4 whose preview and response is the content of my .txt file. But like I said, the server never gets that text, so I'm puzzled.
Any help is greatly appreciated, thanks!
ANSWER
I ended up just using this: JavaScript: Upload file
Client code:
%form{:enctype => 'multipart/form-data', :action => '/parse_opml', :method => 'post'}
%input{:type => 'file', :name => 'file', :id => 'the_o'}
%input{:type => 'submit', :value => 'go'}
Server code:
f = File.open(params[:file].tempfile, 'r')
c = f.read
Works like a charm!
Javascript can't post uploaded files to the server as it is a limitation (for security reasons I assume).
Take a look at this other question regarding posting files posted through javascript:
JavaScript: Upload file
The answer on that questions says you can only do it using flash, but there are also iframe alternatives for upload and post.
Take a look at this as well for an alternative solution:
https://github.com/Widen/fine-uploader
Your ajax request isn't event sent as you return from your onload function before it.
You can send files via ajax on up to date browsers using XHR2
reader.onload = (function(theFile) {
var data = new FormData();
data.append('file',theFile);
$.ajax({
type: 'POST',
processData: false,
contentType: false,
url: "/parse_opml",
data: data,
success: function(details, response) {
console.log('woo!');
},
error: function(data, response) {
console.log('boooo');
}
});
return function(e) {
// Print the contents of the file
var span = document.createElement('span');
span.innerHTML = ['<p>',e.target.result,'</p>'].join('');
document.getElementById('list').insertBefore(span, null);
};
})(f);

using html5 for file upload with ajax and jquery

So i am trying to upload an image along with form data to server. I'm using FileReader API to convert image to data and upload to server. I'm following the code similar to HTML5 uploader using AJAX Jquery.
The data is converted in jquery, but nothing is being sent to server and there is no error generated.
$('#formupload').on('submit', function(e){
e.preventDefault();
var hasError = false;
var file = document.getElementById('file').files[0];
var reader = new FileReader();
reader.readAsDataURL(file);
reader.onload = shipOff;
function shipOff(event) {
result = new Image();
result.src = event.target.result;
var fileName = document.getElementById('file').files[0].name;
$.post('test.php', { data: result, name: fileName });
}
PHP Code
<?php
$data = $_POST['data'];
$fileName = $_POST['name'];
echo $fileName;
$fp = fopen('/uploads/'.$fileName,'w'); //Prepends timestamp to prevent overwriting
fwrite($fp, $data);
fclose($fp);
$returnData = array( "serverFile" => $fileName );
echo json_encode($returnData);
?>
Is the problem due to large image file or FileReader API?
I'm not sure if file upload works with filereaders, but there is a different way to make it work:
var formData = new FormData($(".file_upload_form")[0]);
$.ajax({
url: "upload_file.php", // server script to process data (POST !!!)
type: 'POST',
xhr: function() { // custom xhr
myXhr = $.ajaxSettings.xhr();
if (myXhr.upload) { // check if upload property exists
// for handling the progress of the upload
myXhr.upload.addEventListener('progress', progressHandlingFunction, false);
}
return myXhr;
},
success: function(result) {
console.log($.ajaxSettings.xhr().upload);
alert(result);
},
// Form data
data: formData,
//Options to tell JQuery not to process data or worry about content-type
cache: false,
contentType: "application/octet-stream", // Helps recognize data as bytes
processData: false
});
function progressHandlingFunction(e) {
if (e.lengthComputable) {
$("#progress").text(e.loaded + " / " + e.total);
}
}
This way you send the data to the PHP file and you can use $_FILES to process it. Unfortunately, this does not work in IE as far as I know. There might be plugins available that make this possible in IE, but I don't know any of them.

Categories

Resources