Webcam js upload image to Amazon S3 - javascript

I'm trying to upload an image taken with
Webcam js
directly to Amazon S3
var dataUri = Webcam.snap();
var raw = window.atob(dataUri.replace(/^data\:image\/\w+\;base64\,/, ''));
and after I get the policy (which is correct) I do this
$.ajax({
type: 'POST',
url: amazonUploadUrl,
data: {
file: raw,
contentType: "image/jpeg",
key: key,
AWSAccessKeyId: awsAccessKey,
acl: "public-read",
policy: policy,
signature: signature,
name: "",
Filename: filename
},
dataType: "",
success: function (r1) {
}
});
I've tried sending the encoded image, the decoded image, I've tried modifying the headers. All I keep getting is this
XMLHttpRequest cannot load 'amazon s3 bucket url'. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'my local domain' is therefore not allowed access.
I've added the CORS info on the Amazon bucket.
I'm already uploading images to that bucket using plupload.
I've also uploaded images from a standard without using ajax.
I just can't seem to get this to work.
Any ideas?
Thanks
PS: I've also tried using
jquery webcam plugin
With the same result

You'll need to use the javascript FormData object and native XMLHttpRequest methods to post the data directly to s3. I've tried to do the exact same thing this morning with jQuery and ran into that error message, but native javascript APIs work.
I have a feeling jQuery isn't using CORS by default or is sending across a the wrong header somewhere.
This answer shows how to convert to a format S3 can understand, which may not be necessary in your case.
This should get you started on the form data part:
var fd = new FormData();
fd.append("contentType", "image/jpeg");
fd.append("key", key);
fd.append("AWSAccessKeyId", awsAccessKey);
fd.append("acl", "public-read");
fd.append("policy", policy);
fd.append("signature", signature);
fd.append('filename', "");
fd.append('file', raw);
var xhr = new XMLHttpRequest();
xhr.open('POST', amazonUploadUrl);
xhr.addEventListener('load', function(e) {
console.log('uploaded!', e) // Successful upload!
});
// Optionally bind to other xhr events, like error, progress, or abort.
// Using native XHR2 is nice because the progress event works and you
// can tack on upload progress counters.
xhr.send(fd);

Related

javascript post blob to back-end java

i recorded a video using javascript (with recordRTC) , now i have it as a blob :
mediaRecorder.onstop = (ev)=>{
let blob = new Blob(chunks, { 'type' : 'video/mp4;' });
chunks = [];
let videoURL = window.URL.createObjectURL(blob);
vidSave.src = videoURL;
var file = new File([blob], 'video.mp4', {
type: 'video/mp4'
});
invokeSaveAsDialog(file);
// my attempt to send this blod //
let req = new XMLHttpRequest();
let formData = new FormData();
formData.append("video", blob);
req.open("POST", 'http://localhost:8081/avi/recieveAndParseVideo');
req.send(formData);
//
}
now i am trying to send it to my back-end application i dont know how , i created a java method:
#PostMapping("/recieveAndParseVideo")
public String uploadingPost(#RequestBody MultipartFile uploadingFile) throws IllegalStateException, IOException {
System.out.println(uploadingFile);
File file = new File("C://" + uploadingFile.getOriginalFilename());
uploadingFile.transferTo(file);
return file.getName();
}
when i execute the top javascript method it throws this exception:
Access to XMLHttpRequest at 'http://localhost:8081/avi/recieveAndParseVideo' from origin 'http://localhost:4200' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.
guys i dont even know if this is the right way to send a post via javascript , and is my java code correct to receive the file?
please help
Welcome to the terrible and wonderful world of CORS. Cross-Origin Resource Sharing is what keeps you and me safe while we're browsing the Internet. Without it, websites could download and perform any code or content they wanted.
Imagine a website, foo.example was compromised. Someone found a way to make it download malicious code from their own website, bar.example. Without CORS policies, your browser would gladly run that code! With CORS, your browser says 'Hey wait a second, I'm at foo.example, why would I run code from another website?'
For local testing, your best solution is to install and configure a CORS plugin to your browser. An example for FireFox is CORS Everywhere, found here. This will let you access resources at localhost:8081 from localhost:4200.
For production, your server will need to send the appropriate response headers to your website, e.g. Access-Control-Allow-Origin: yourWebsite.example
More information about why and how CORS works

Google Drive API V3 Javascript - Create File with Content

This question has been asked before, but the answer was using API V2. The google documentation does not clarify how to create a file with its content using javascript client code. I tried using the code listed under Node, however, it only creates the file, it does not insert any content. Here is my code:
let fileMetadata = {
'name': name,
parents: [parentId]
};
let media = {
mimeType: 'text/plain',
body: 'content inside file'
};
gapi.client.drive.files.create({
resource: fileMetadata,
media,
fields: 'id'
})
.then(response => {
console.log('response: ', response);
})
.catch(() => {
console.log('something is wrong');
});
Can someone help me insert content into files please?
How about this sample script? In my environment, although gapi.client.drive.files.create() can create an empty file on Google Drive, it cannot directly upload files including contents. I think that this might not be able to upload files and metadata with the multipart/related, although this might be resolved by the future update. So now, as one of workarounds, I use XMLHttpRequest.
Before you use this sample script, please confirm the following points.
In your situation, you have already been able to create files using gapi. In my script, the access token is retrieved using gapi.
When you use this script, please set fileContent and metadata.
Sample script :
In this sample script, a text file including contents is created under a folder.
var fileContent = 'sample text'; // As a sample, upload a text file.
var file = new Blob([fileContent], {type: 'text/plain'});
var metadata = {
'name': 'sampleName', // Filename at Google Drive
'mimeType': 'text/plain', // mimeType at Google Drive
'parents': ['### folder ID ###'], // Folder ID at Google Drive
};
var accessToken = gapi.auth.getToken().access_token; // Here gapi is used for retrieving the access token.
var form = new FormData();
form.append('metadata', new Blob([JSON.stringify(metadata)], {type: 'application/json'}));
form.append('file', file);
var xhr = new XMLHttpRequest();
xhr.open('post', 'https://www.googleapis.com/upload/drive/v3/files?uploadType=multipart&fields=id');
xhr.setRequestHeader('Authorization', 'Bearer ' + accessToken);
xhr.responseType = 'json';
xhr.onload = () => {
console.log(xhr.response.id); // Retrieve uploaded file ID.
};
xhr.send(form);
Request body :
In this script, form is as follows. This is sent to Google Drive using the create method of Drive API.
------WebKitFormBoundaryxX0XmxgooMjdUECR
Content-Disposition: form-data; name="metadata"; filename="blob"
Content-Type: application/json
{"name":"sampleName","mimeType":"text/plain","parents":["#####"]}
------WebKitFormBoundaryxX0XmxgooMjdUECR
Content-Disposition: form-data; name="file"; filename="blob"
Content-Type: text/plain
sample text
------WebKitFormBoundaryxX0XmxgooMjdUECR--
In my environment, I confirmed that this works fine. But if this didn't work in your environment, I'm sorry.

Google Drive API: Correct way to upload binary files via the Multipart API

I'm trying to upload a binary file to Google Drive via the
multipart upload API v3.
Here's the hex representation of the content of the file:
FF FE
For some reason the above content gets encoded as UTF-8 (I assume)
when I try to POST it, enclosed in a multipart payload:
--BOUNDARY
Content-Type: application/json
{"name": "F.ini"}
--BOUNDARY
Content-Type: application/octet-stream
ÿþ <-- in the outbound request, this gets UTF-8 encoded
--BOUNDARY--
Hex representation of the file that ultimately gets stored on server side:
C3 BF C3 BE
The problem only occurs in the sending stage:
if I check the length of the content read from the file I always get 2;
regardless of whether I use FileReader#readAsBinaryString or FileReader#readAsArrayBuffer
(producing a string with length 2, and an ArrayBuffer with byteLength 2, respectively).
Here's the minimal code that I'm using to generate the multipart payload:
file = picker.files[0]; // 'picker' is a file picker
reader = new FileReader();
reader.onload = function (e) {
content = e.target.result;
boundary = "BOUNDARY";
meta = '{"name": "' + file.name + '"}';
console.log(content.length); // gives 2 as expected
payload = [
"--" + boundary, "Content-Type: application/json", "", meta, "", "--" + boundary,
"Content-Type: application/octet-stream", "", content, "--" + boundary + "--"
].join("\r\n");
console.log(payload.length); // say this gives n
xhr = new XMLHttpRequest();
xhr.open("POST", "/", false);
xhr.setRequestHeader("Content-Type", "multipart/related; boundary=" + boundary);
xhr.send(payload); // this produces a request with a 'Content-Length: n+2' header
// (corresponding to the length increase due to UTF-8 encoding)
};
reader.readAsBinaryString(file);
My question is twofold:
Is there a way to avoid this automatic UTF-8 encoding? (Probably not, because
this answer
implies that the UTF-8 encoding is part of the XHR spec.)
If not, what is the correct way to "inform" the Drive API that my file content is UTF-8 encoded?
I have tried these approaches, with no success:
appending ; charset=utf-8 or ; charset=UTF-8 to the binary part's Content-Type header
doing the same to the HTTP header on the parent request
(Content-Type: multipart/related; boundary=blablabla, charset=utf-8;
also tried replacing the comma with a semicolon)
I need the multipart API because AFAIU the "simple" API
does not allow me to upload into a folder
(it only accepts a filename as metadata, via the Slug HTTP header,
whereas the JSON metadata object in the multipart case allows a parent folder ID to be specified as well).
(Just thought of mentioning this because the "simple" API handles things correctly
when I directly POST the File (from the picker) or ArrayBuffer (from FileReader#readAsArrayBuffer) as the XHR's payload.)
I do not want to utilize any third-party libraries because
I want to keep things as light as possible, and
keeping aside reinventing-the-wheel and best-practices stuff, anything that is accomplished by a third party library should be doable via plain JS as well (this is just a fun exercise).
For the sake of completeness I tried uploading the same file via the GDrive web interface, and it got uploaded just fine;
however the web interface seems to base64-encode the payload, which I would rather like to avoid
(as it unnecessarily bloats up the payload, esp. for larger payloads which is my eventual goal).
How about this modification?
Modification points:
Used new FormData() for creating the multipart/form-data.
Used reader.readAsArrayBuffer(file) instead of reader.readAsBinaryString(file).
Send the file as a blob. In this case, the data is sent as application/octet-stream.
Modified script:
file = picker.files[0]; // 'picker' is a file picker
reader = new FileReader();
reader.onload = function (e) {
var content = new Blob([file]);
var meta = {name: file.name, mimeType: file.type};
var accessToken = gapi.auth.getToken().access_token;
var payload = new FormData();
payload.append('metadata', new Blob([JSON.stringify(meta)], {type: 'application/json'}));
payload.append('file', content);
xhr = new XMLHttpRequest();
xhr.open('post', 'https://www.googleapis.com/upload/drive/v3/files?uploadType=multipart');
xhr.setRequestHeader('Authorization', 'Bearer ' + accessToken);
xhr.onload = function() {
console.log(xhr.response);
};
xhr.send(payload);
};
reader.readAsArrayBuffer(file);
Note:
In this modified script, I put the endpoint and the header including the access token. So please modify this for your environment.
In this case, I used a scope of https://www.googleapis.com/auth/drive.
Reference:
Using FormData Objects
In my environment, I could confirmed that this script worked. But if this didn't work in your environment, I'm sorry.

How to load foreign image via POST request in browser?

My web application (HTML5 + JavaScript) needs to display PNG images that are generated by foreign web service.
However, that web service supports POST requests only. (More exactly, it does provide GET requests, but I have to transmit large arguments, due to which the GET URL becomes too long.)
Also, the web service has a different domain than the web application, and doesn't supply proper CORS headers, so Ajax (XMLHTTPRequest) doesn't work.
Is it still possible for my web application to load and display the foreign image via POST request?
I'm asking for a solution that is different from the following nasty workarounds, which are already well-known to me:
without setting up a local proxy that translates the request (and also circumvents the same-origin policy)
without using the remote proxy of some stranger
without using Flash
without using Java Applets
without using OS specific functionality such as ActiveX controls
However, a solution that fails to work with Internet Explorer is acceptible. Even a Firefox or Chrome specific solution is appreciated.
Horrible hack:
Submit a form to an iframe and have the image displayed in the iframe.
(But don't do this, it sounds like the web server is designed to avoid having images being embedded directly in other sites.)
I have some possible solutions...
Solution 1
If your image is less that 25kb you can do the following via YQL: select * from data.uri where url="http://jquery.com/jquery-wp-content/themes/jquery/images/logo-jquery#2x.png" As a result you can just grab the base64 image and carry on. To do a POST via YQL you should add something like and postdata="foo=foo&bar=bar" check out this article.
Caveat: The performance of this method is probably not great. There's a fair amount of latency making the hop from the end user to YQL to the service and then going all the way back. Also there is some server side processing YQL does to base64 encode the image and deliver some JSON response.
Solution 2
Get CORS enabled or go through some other proxy. Once you do so, if you still can't get base64 data then you need to do 2 things. First add a jQuery transport that handles binary. Second process the binary blob and convert it to base64.
Here is a jQuery Binary Transport I found
$.ajaxTransport("+binary", function(options, originalOptions, jqXHR){
// check for conditions and support for blob / arraybuffer response type
if (window.FormData && ((options.dataType && (options.dataType == 'binary')) || (options.data && ((window.ArrayBuffer && options.data instanceof ArrayBuffer) || (window.Blob && options.data instanceof Blob)))))
{
return {
// create new XMLHttpRequest
send: function(headers, callback){
// setup all variables
var xhr = new XMLHttpRequest(),
url = options.url,
type = options.type,
async = options.async || true,
// blob or arraybuffer. Default is blob
dataType = options.responseType || "blob",
data = options.data || null,
username = options.username || null,
password = options.password || null;
xhr.addEventListener('load', function(){
var data = {};
data[options.dataType] = xhr.response;
// make callback and send data
callback(xhr.status, xhr.statusText, data, xhr.getAllResponseHeaders());
});
xhr.open(type, url, async, username, password);
// setup custom headers
for (var i in headers ) {
xhr.setRequestHeader(i, headers[i] );
}
xhr.responseType = dataType;
xhr.send(data);
},
abort: function(){
jqXHR.abort();
}
};
}
});
Once you add the transport you can make any sort of AJAX request.
$.ajax({
type: "POST",
url: 'http://myservice.com/service/v1/somethingsomething',
dataType: 'binary',
success: function(imgData) {
var img = new Image(),
reader = new window.FileReader();
reader.readAsDataURL(imgData);
reader.onloadend = function() {
img.src = reader.result
$('#logo-events').append(img);
}
}
});
The reader should take the Blob and output a base64 version. When the reader is done converting/reading it will create and image and append it somewhere. GET or POST should not matter any more.
I found this related question: Post data to JsonP
And I think that it could be applicable in your case.
Basically, fire your jsonp request to your server (same-origin-policy should not be a problem), and load the response an <img>
Like #Quentin's answer, this hack uses a (hidden) Iframe

Trying to upload file stored using HTML 5 File API

I'm piecing together tutorials from the web to be able to build a tool where users can upload images offline in an HTML5 app to filesystem storage along with some personal details and when they are online, they can "sync" which uploads the files and their details to the server.
I've managed to get a simple page up that stores images in file storage & sizes them down but I am unable to figure out how to post them using XMLHttpRequest. I've managed to push just the file data and store it one by one by using php://input (taken from Upload file from HTML5 Filesystem by XMLHttpRequest) but I need it to be uploaded as a form field that I can retrieve via $_FILES.
This function in particular:
function (fileName, successFct) {
getFileSystem(function (fileSystem) {
var fd = new FormData();
var xhr = new XMLHttpRequest();
xhr.open('POST', 'upload.php', true);
xhr.onload = function(e) {
if (this.status == 200) {
console.log(this.responseText);
}
};
fileSystem.root.getFile(fileName, {}, function (fileEntry) {
fileEntry.file(function(file) {
fd.append('file' + i, file);
fd.append('name' + i, 'name' + i);
});
}, errorFct);
xhr.send(fd);
}
);
};
Full code can be seen # http://pastebin.com/W0x9q6YH
In upload.php if I do the following
print_r($_FILES);
print_r($_POST);
It just shows two empty arrays.
Struggling with a similar problem: one thing I noticed about your code, you do not set your Content-Type header to multipart/form-data.
I do not have a working sample yet, but I'm pretty sure to use FormData, you need that old multipart/form-data magic.

Categories

Resources