ember file upload to rails, encoding and decoding with base64 - ruby-on-rails

I'm almost there, but I'm having an issue with decoding of the file. When decoding the file is not correct.
The code that I use to upload the file:
createDataSet: function() {
var data = new FormData();
data.append('original_filename', this.get('fileName'));
data.append('datafile', this.get('newData'));
data.append('project_id', this.get('content.id'));
data.append('name', this.get('content.name'));
$.ajax({
url: '/data_sets.json',
data: data,
cache: false,
contentType: false,
processData: false,
dataType: 'json',
type: 'POST',
success: function(data) {
alert('ok');
},
error: function(xhr, data, errorThrown) {
alert('error');
}
});
}
On the Rails side I'm trying to pick this up with the following method:
def create
# take care of the attachement
datasetfilename = Pathname.new(params[:original_filename]).basename
newfile = File.open(datasetfilename, 'w') do |f|
f.write(Base64.decode64(params[:datafile]))
end
#dataset = DataSet.new
#active_data_set = #dataset.active_data_sets.build
#active_data_set.project_id = params[:project_id]
#active_data_set.save
#dataset.name = params[:name]
#dataset.filename = datasetfilename
#dataset.tempfilename = #dataset.savefile newfile
#dataset.save
end
If I use File.open(datasetfilename, 'w') I get an error like this one Encoding::UndefinedConversionError - "\xAB" from ASCII-8BIT to UTF-8. On the other hand, if I open with 'wb' the resulting file is mingled and can't be read.
I already added the meta tag for the file encoding <meta charset="utf-8" /> but without any difference.
If anybody has any hint that would be appreciated.

Just got this working in one of my own controllers, there are 2 main issues:
1) to resolve the encoding issue, use "w:binary" as the write flag instead of "w" (defaults to ASCII)
2) the :datafile params includes some header info "data:text/csv;base64,SUR4CUluZ...", I'm currently splitting on "," but might be better served to decode everything beyond "base64," as I'm not sure if additional commas are allowed.
My working code (slightly different parameter names):
if params.key?(:img_file)
header, data = params[:img_file].split(',')
img_type = header.match(/image\/([a-z]{1,11});/)[1]
file_path = "imgtodo/fund_#{#fund.id}.#{img_type}"
File.open(Rails.root.join('public',file_path).to_s, 'w:binary') do |f|
f.write(Base64.decode64(data))
end
end

Related

Why does S3 change content type of my CSV

I'm using ruby on rails to generate presigned url so I can upload a CSV file. This works perfectly, I can even get the CSV using a presigned URL. The problem is when I get the CSV file a random block of text appears at the top of the csv.
------WebKitFormBoundaryrnmGKBwtkSrSvPUR
Content-Disposition: form-data; name="file"; filename="MOCK_DATA.csv"
Content-Type: application/octet-stream
id,first_name,last_name,email,gender,job_title,city,country
1,Emlyn,Dayce,edayce0#example.com,Male,Quality Control Specialist,Debrecen,Hungary
So when I try to loop through the csv using the below code:
require 'csv'
require 'open-uri'
csv = CSV.new(open(presigned_url), headers: false)
csv.each do |csv|
puts csv.to_s
end
I get the following error:
CSV::MalformedCSVError (Illegal quoting in line 2.):
Which is refering to the line:
csv.each do |csv|
Any solutions on a: how to remove this block of text before looping / while parsing the CSV. Or better yet preventing the block of text from being added in the first place using S3 Presigned URLs.
Note: I have tried to add
content_type: 'text/csv'
to presigned request, however, it doesn't recognize the param.
UPLOADING PROCESS:
I am using Vuejs to upload the csv to S3.
let formData = new FormData();
formData.append("file", this.$refs.file.files[0], { contentType: 'text/csv'
});
this.axios
.put(this.presigned_url, formData, {
headers: {
'Content-Type': 'multipart/form-data'
}
})
.then(response => {
// Handle response
if(response.status == 200){
this.original_file_name = "Processing CSV..."
this.processCsv();
}
});
I was struggling with the same issue, the problem is that you are sending the entire form into S3 and not just the file.
A correct code snippet in your case would be something like this:
this.axios
.put(this.presigned_url, this.$refs.file.files[0], {
headers: {
'Content-Type': 'text/csv'
}
})
.then(response => {
// Handle response
if(response.status == 200){
this.original_file_name = "Processing CSV..."
this.processCsv();
}
});

how to save a blob file using carrierwave in rails

So i have a requirement where i record a video and save it in the database, the recording of the video is working fine, only thing is it generates a blob file, then i use js to send the blob file to the server. This are my params
{"testqwe"=>{"attr"=>"blob:http://localhost:3000/6f12f123-b1d0-7bfc-6b15-d3b54341946"}, "controller"=>"myControler", "action"=>"test"}
i have an uploader in place , but it does not save anything.
so how can i save this using carierwave to my database?
here is my javascript
mediaRecorder.onstop = (ev) ->
blob = new Blob(chunks, 'type': 'video/mp4;')
chunks = []
videoURL = window.URL.createObjectURL(blob)
vidSave.src = videoURL
$.ajax
type: 'POST'
content_type: "video/webm"
url: '/test'
enctype: "multipart/form-data"
data: testqwe: attr: videoURL
return
any one still trying to figure out this, u can refer this link
How to pass blob url to rails create method by ajax
mediaRecorder.onstop = (ev) ->
blob = new Blob(chunks, 'type': 'video/mp4;')
chunks = []
videoURL = window.URL.createObjectURL(blob)
vidSave.src = videoURL
formData = new FormData
formData.append('testqwe[attr]', blob);
$.ajax
type: 'POST'
url: '/test'
processData: false
contentType: false
data: formData
return
Send and save the audio/video data as a file

Posting/receiving JSON object

So I am using this code to post:
$.ajax({
url: '/validator/ValidationController/validate',
data : JSON.stringify(parameters),
contentType : 'application/json',
type : 'POST'
})
And this to receive, both being triggered by the same button press. But it's just getting a null object.
def validate(){
Thread.currentThread().sleep(1000)
def parameters = request.JSON;
assert parameters.a == "a_value";
}
When I hover over the validate function, it's referred to as: Object validator.ValidationController.validate() I'm assuming the url is wrong.
Note: I am pretty inexperienced with this, speaking to me like I'm 5 is encouraged!
We would need more code to see how you are sending and receiving but it seems like you are not handling the asynchronous aspect. In simple terms, you are sending out the request and immediately trying to handle the response, even though it is not back yet and even though you tried to sleep. Check out the complete config for the ajax function. Something like this:
$.ajax({
url: '/validator/ValidationController/validate',
data : JSON.stringify(parameters),
contentType : 'application/json',
type : 'POST',
complete: function(request, success){
validate(request)
}
})
def validate(request){
Thread.currentThread().sleep(1000)
def parameters = request.JSON;
assert parameters.a == "a_value";
}

give dynamic action name in Url.action javascript

I want to give dynamic action name in Url.action through javascript.
// I want to change Index name by dynamic
$.ajax({
url: '#Url.Action("Index", "Home")',
type: "Post",
data: { Surveyid: surveyid, Category: catcode },
success: function (data) {
window.location.href = data.Url
}
like
var x="xxxx";
#Url.Action(x,"Home") -> not working throws error
#Url.Action(x.toString(),"Home") -> not working
then how can i ?
Url.Action is server generated, whereas it seems you want to change the action on the browser. What you can do is tokenize the Action, get Url.Action to generate the tokenized URL, and then substitute this in js:
var jsUrl = '#Url.Action("##", "Home")'; // ## is the token
$.ajax({
url: jsUrl.replace('##', someDynamicAction),
...
(You may need to do the same for the controller)
Edit
My conscience has gotten the better of me - doing this isn't a good idea, given that any invalid action name (or a change in the Controller or Action names) will only be picked up at run time e.g. with 404 errors.
The number of controllers and actions that you need to ajax to should be finite, and T4MVC has already solved this kind of issue.
You can create the urls to the various links:
var urlToIndex = '#Url.Action(MyControllerAssembly.Index.Home())))';
var urlToOtherAction = ...
... etc for all actions needed in the 'switch' for ajax call.
and then choose the appropriate URL for your ajax call. (T4MVC also has methods Url.JavaScriptReplacableUrl and Ajax.ActionLink although for slightly different scenarios)
Best way to use urls in your mvc application is that you define a global app_url in layout page like following:
_Layout.cshtml
<script>
var app_root = '#Url.Content("~/")';
</script>
and use in content page
any_page that inherited from _Layout.cshtml
$.ajax({
url: app_root + 'Home/Index', // or url: app_root + 'Home/' + x
something odd in your example, but I believe what you are trying to do is this
function axajThis(numberthing,path) {
var newUrl = "htttp://somplace/"+path;
/* and what ever the number x is doing */
$.ajax({
url: newUrl,
type: "Post",
data: ....
});
};
}
axajThis(x,"Home");
Little more info needed on what 'x' is.

Can't send complex json data to server using prototype and rails

I'm trying to send the following data to the server but at the server side I don't see the json parameter that I'm sending. Can anyone tell me what I'm doing wrong?
Below you can see the code.
Prototype:
send_data_url = "change"
hash = $H({"blocks": [{"h": "2", "area": [{"width": "96%", "els": [{"title": "first", "mand": true}, {"title": "second", "mand": false}]}]}]});
var request_array_json = hash.toJSON();
new Ajax.Request(send_data_url, {
method: 'post',
parameters: request_array_json,
contentType: 'application/json;'
});
Rails:
def change()
debugger
my_json = ActiveSupport::JSON.decode(params["_json"])
end
In the controller I see that the params object does not have the json parameter.
It only shows the action and the controller:
{"action"=>"change", "id"=>nil, "controller"=>"default/test"}
Note: I'm using prototype 1.6 qnd rails 2.3.2.
I found a solution using a plugin called json_request.
To get this working nicely, I also wrapped Ajax.Request with a new class that can send complex JSON objects. Example code:
Ajax.JSON = Class.create(Ajax.Request, {
initialize: function($super, url, options) {
options = options || {};
options.contentType = ‘application/x-www-form-urlencoded’;
options.postBody = Object.toJSON(options.object);
$super(url, options);
}
});
new Ajax.JSON(url, { object: myObject });
Read more: http://labnotes.org/2007/12/11/json_request-handling-json-request-in-rails-20/comment-page-1/#comment-143190#ixzz0n5iKnO60

Resources