I'm developing a Javascript app and I need to use the Mediafire REST API to upload a file. (See upload ducmentation here).
Following this MDN tutorial, and some research, I've written the code below, but it seems it's not working... Note that I don't need for the moment to control the progress and so on, I only want to do the most basic upload operation possible...
Also note that I could a different code, and even jQuery or other (free) libraries, so if you have a better code to upload a file I'd be really grateful...
var controller = this;
var file = $("#file").get(0).files[0];
//The file is correctly retrieved here...
var xhr = new XMLHttpRequest();
xhr.open('POST', 'http://www.mediafire.com/api/upload/upload.php?session_token=' + controller.sessionToken.token);
//(The session_token is valid)
xhr.overrideMimeType('text/plain; charset=x-user-defined');
xhr.setRequestHeader('x-filesize', file.size);
var reader = new FileReader();
reader.onload = function (evt) {
var uInt8Array = new Uint8Array(evt.target.result);
//It seems that here the ArrayBuffer is read correctly,
//and I converted it to a ArrayBufferView because Chrome suggested it...
xhr.send(uInt8Array);
};
reader.readAsArrayBuffer(file);
I can't tell the concrete error, I only know that nothing is happens... but maybe looking at the code you can see some obvious error... The only thing I see is this in Chrome's console:
Note: I know the quality of this question is not the desired and it's TOO vague, but I tried to do my best taking into account that I'm completely new to ALL these technologies...
The presence of an OPTIONS request and the presence of specific headers in the OPTIONS request indicates that your POST request is a cross-domain request. The user agent, following the CORS spec, is first sending an OPTIONS request. This is also called a preflight request, and it is sent, in your case, due to the non-standard header you are including (x-filesize) and the fact that the Content-Type is not form-encoded, MPE, or text/plain. You can either deal with the OPTIONS request server-side, or make appropriate changes to your request so that a preflight is not required. Either way, you are going to have to deal with CORS requests server-side since you are apparently making a cross-domain request. You can read more about CORS in this excellent MDN article.
P.S. Why are you using FileReader here? Just send the File object via XHR, or, better yet, append the File to a FormData object and send that.
Related
I'm a fairly novice programmer currently working on a chrome extension intended to automatically restore the response folders of google forms. The extension mainly operates by intercepting HttpRequests made by the form upon launch, one of these requests is crucial to the operation of the extension. A "checkfolders" POST request is made by the form, and, if intercepted, copied, and than sent from the extension, the full response body is returned. It's relatively small containing a true or false variable:
{"fileuploadfolderswritable":true,"status":0}
This variable indicates whether or not the form needs restoration. Looking at the network requests made from my Chrome Extension, the request works perfectly fine, and the full response body is returned with no errors. However, req.response as shown below, comes up as null.
function Get_Folder_Status(url){ //var url = Intercepted Http Response
const req = new XMLHttpRequest();
req.open("POST", url.href, true); //url.href = Request Url
req.setRequestHeader("Content-type", "application/x-www-form-urlencoded"); //Send Request to Check Folder Status of Form
req.responseType = "json";
req.onload = Check_Folder(req.response)
req.send()
}
There is most likely some small detail that I'm missing, I've already spent quite a while fiddling with variables like the responseType and headers with no success. I've viewed other threads about a "null" response with no direct answer to my specific problem, so I hope I was descriptive enough to give some insight to what the issue may be. The sending of the request has no errors whatsoever, so it must be how I'm handling the response.
I am trying to make a GET request to AWS S3 using pure Javascript. This is because I am unfortunately no longer able to use the SDK for all of my requests. I have been attempting to follow the documentation provided by Amazon, however I have made very little progress. So far, I have only been able to generate my signature key. I would be enthused if someone could post an example of pure Javascript that makes a simple call to retrieve an object or even lists all of the objects with a specific prefix. I am, to be perfectly honest, completely lost reading their documentation. It seems like it is only useful for people who are intimately familiar with making these calls. #1 and #2 on this image here are what I'm struggling with. I think I sort of understand what they are wanting but I don't know how to fully translate it into an actual request. Unfortunately the code examples on their docs are very few and far between - and a lot of them are just pseudocode/small fractions of the whole thing
edit: Hello is anyone even reading this
edit2: Here's some stuff that isn't working that I'm trying to figure out how to do
var signingKey = getSigningKey(dateStamp, secretKey, regionName, serviceName);
var time = new Date();
//fullURL is something like https://s3.amazon.aws.com/{bucketName}/{imageName}
time = time.toISOString();
time = time.replace(/:/g, '').replace(/-/g,'');
time = time.substring(0,time.indexOf('.'))+"Z";
var request = new XMLHttpRequest();
var canonString = "GET\n"+
encodeURI(fullURL)+"\n"+
encodeURI("Key=asd.jpeg")+"\n"+
"host:s3.amazonaws.com\n"+
"x-amz-content-sha256:"+CryptoJS.SHA256("").toString()+"\n"+
"host;x-amz-content-sha256\n"+
CryptoJS.SHA256("").toString();
var stringToSign = "AWS4-HMAC-SHA256\n"+
time+"\n"+
"20181002/us-east-1/s3/aws4_request\n"+
CryptoJS.SHA256(canonString).toString();
var authString = CryptoJS.HmacSHA256(signingKey, stringToSign).toString();
var queryString = "GET https://s3.amazonaws.com/?Action=GetObject&Version=2010-05-08 HTTP/1.1\n"+
"Authorization: AWS4-HMAC-SHA256 Credential="+accessKey+"/20181002/us-east-1/s3/aws4_request, SignedHeaders=host;x-amz-date, Signature="+authString+"\n"+
"host: s3.amazonaws.com\n"+
"x-amz-date: "+time+"\n";
request.open("GET", "https://s3.amazonaws.com/?Action=GetObject&Version=2010-05-08", false);
request.setRequestHeader("Authorization", "AWS4-HMAC-SHA256 Credential="+accessKey+"/20181002/us-east-1/s3/aws4_request, SignedHeaders=host;x-amz-date, Signature="+authString);
request.setRequestHeader("host", "s3.amazonaws.com");
request.setRequestHeader("x-amz-date", time);
request.send();
edit3: Here are a bunch of errors I get, presumably because I have no idea what I'm doing.
index.js:61 Refused to set unsafe header "host"
index.js:63 OPTIONS https://s3.amazonaws.com/?Action=GetObject&Version=2010-05-08 403 (Forbidden)
index.js:63 Failed to load https://s3.amazonaws.com/?Action=GetObject&Version=2010-05-08: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'null' is therefore not allowed access.
index.js:63 Uncaught DOMException: Failed to execute 'send' on 'XMLHttpRequest': Failed to load 'https://s3.amazonaws.com/?Action=GetObject&Version=2010-05-08'.
You might want to use the SDK, combined with the browser debugger to figure out how the SDK formats the request. In the Chrome debugger Network tab, you can copy the request as a javascript fetch. This will show all the headers you need to set. You can then use this as a basis for your non-SDK code.
I know it's possible to load any kind of document from any domain from JavaScript (without necessarily being able to peek at its content), but it usually concerns regular GET requests. What about POST?
Is it possible to make an HTTP POST request from JavaScript to any domain name? (I'm specifically interested in form submissions.)
If so, how?
As per some answers on a nearby question, «HTTP GET request in JavaScript?», you might use XMLHttpRequest, since, according to the docs, the POST method is supported, too.
http://www.w3.org/TR/XMLHttpRequest/
https://developer.mozilla.org/en-US/docs/DOM/XMLHttpRequest
A sample code from the above w3.org document:
function log(message) {
var client = new XMLHttpRequest();
client.open("POST", "/log");
client.setRequestHeader("Content-Type", "text/plain;charset=UTF-8");
client.send(message);
}
However, it would seem like in order for it to work with POST requests to domains unrelated to yours (where instead of "/log", a complete http or https URL is specified), the Cross-Origin Resource Sharing may have to be supported and enabled on the target server, as per https://developer.mozilla.org/en-US/docs/HTTP/Access_control_CORS#Simple_requests.
So, it seems like, at least through XMLHttpRequest, you cannot make form submissions through POST requests (in fact, looks like even GET requests won't fly, either).
I'm trying to send multipart/form-data with following JavaScript and jQuery:
var formData = new FormData();
formData.append("projectName", $("#projectNameInput").val());
var file = $("#fileInput")[0].files[0];
formData.append("content", file);
var xhr = new XMLHttpRequest();
xhr.open('POST', '/project', true);
xhr.onload = function(ev) {
// Handling logic omitted
};
xhr.send(formData);
However, some client browsers (Firefox and Chrome) receive 400 Bad Request from the server. While examining the headers and request payload I discovered that some browsers set explicit content type for the file as follows:
------WebKitFormBoundaryEuDIpEU2Ci8VNwNJ
Content-Disposition: form-data; name="content"; filename="testfile.ext"
Content-Type: EXT Project Data (64bit)
------WebKitFormBoundaryEuDIpEU2Ci8VNwNJ
In a working request the Content-Type should be as follows: Content-Type: application/octet-stream, which the server can handle properly.
I suspect this has something to do with browser's configuration or file associations. Is there a way to explicitly set the content type for the file part of the request?
The problem occurs with some users using Firefox and Chrome. However, some users are able to upload succesfully using Chrome and Firefox. IE is not supported by our application.
Ok, we managed to figure out this issue. It turned out that the content type registered to the client system was actually malformed on some client machines, that had certain third-party application installed.
We cannot programmatically change the content type browser sets for the part.
As Michael-O pointed out, you should always use content-types registered with the IANA. Here's a link to the standard.
In this case it was third-party software that registered illegal content type to client's system. Content type may not contain white spaces, so the content type EXT Project Data is clearly illegal. We fixed the issue by changing the registered content type to a custom content type. So the content type we are now using is application/x-ext-project-data, which is then handled properly on the server side.
Access to restricted URI denied" code: "1012 [Break On This Error]
xhttp.send(null);
function getXML(xml_file) {
if (window.XMLHttpRequest) {
var xhttp = new XMLHttpRequest(); // Cretes a instantce of XMLHttpRequest object
}
else {
var xhttp = new ActiveXObject("Microsoft.XMLHTTP"); // for IE 5/6
}
xhttp.open("GET",xml_file,false);
xhttp.send(null);
var xmlDoc = xhttp.responseXML;
return (xmlDoc);
}
I'm trying to get data from a XML file using JavaScript. Im using Firebug to test and debug on Firefox.
The above error is what I'm getting. It works in other places i used the same before, why is acting weird here?
Can someone help me why it's occuring?
Update:
http://jquery-howto.blogspot.com/2008/12/access-to-restricted-uri-denied-code.html
I found this link explaining the cause of the problem. But I didn't get what the solution given means can someone elaborate?
Another possible cause of this is when you are working with a .html file directly on the file system. For example, if you're accessing it using this url in your browser: C:/Users/Someguy/Desktop/MyProject/index.html
If that then has to make an ajax request, the ajax request will fail because ajax requests to the filesystem are restricted. To fix this, setup a webserver that points localhost to C:/Users/Someguy/Desktop/MyProject and access it from http://localhost/index.html
Sounds like you are breaking the same origin policy.
Sub domains, different ports, different protocols are considered different domains.
Try adding Access-Control-Allow-Origin:* header to the server side script that feeds you the XML. If you don't do it in PHP (where you can use header()) and try to read a raw XML file, you probably have to set the header in a .htaccess file by adding Header set Access-Control-Allow-Origin "*". In addition you might need to add Access-Control-Allow-Headers:*.
Also I'd recommend to replace the * in production mode to disallow everybody from reading your data and instead add your own url there.
Without code impossible to say, but you could be running foul of the cross-site ajax limitation: you cannot make ajax requests to other domains.