Send raw file data from JavaScript to ASP.NET WebApi - javascript

I am fetching a file from Google Drive using Picker API. I have successfully got file data from downloadUrl:
var xhr = new XMLHttpRequest();
xhr.open('GET', file.downloadUrl);
xhr.setRequestHeader('Authorization', 'Bearer ' + accessToken);
xhr.onload = function () {
fileRecievedCallback(xhr.responseText, doc.name);
};
I have file data in xhr.responseText, Now I want to send this byte string to .Net Web api and convert that to file and save to disc. I can send this file data to web api. Question is how do I read this byte string in C# and convert it to file and save to disk?

Related

405 Method not allowed when downloading a file from google drive

I'm trying to download a file from google drive, but I get a 405 Method not allowed
I have a valid token and I can upload a file, but downloading it using the fileId from the upload doesn't work. What am I doing wrong?
var xhr = new XMLHttpRequest();
xhr.open('GET', 'https://www.googleapis.com/upload/drive/v3/files/'+fileId);
xhr.setRequestHeader('Authorization', 'Bearer ' + token);
xhr.onload = () => {
console.log(JSON.stringify(xhr.response,true,4));
};
xhr.send();
I believe your goal and situation as follows.
You want to download a file from Google Drive.
Your access token can be used for downloading the file from Google Drive using Drive API.
For this, I would like to propose the following modification.
Modification points:
I think that in your script, the endpoint of 'https://www.googleapis.com/upload/drive/v3/files/'+fileId cannot be used for downloading the file from Google Drive.
At Google Drive API, the method for downloading the file is different between Google Docs and others. Google Docs files are Google Document, Google Spreadsheet, Google Slides and so on.
From your question, I couldn't understand about the file type you want to download. So in this answer, I would like to propose the following 2 patterns.
Pattern 1:
When fileId is NOT Google Docs file, you can use the following script. The method of Files: get in Drive API is used. In this case, if the file of file ID is the text file, you can see the file content in the console.
Modified script:
var xhr = new XMLHttpRequest();
xhr.open('GET', 'https://www.googleapis.com/drive/v3/files/' + fileId + '?alt=media');
xhr.setRequestHeader('Authorization', 'Bearer ' + token);
xhr.onload = () => {
console.log(JSON.stringify(xhr.response,true,4));
};
xhr.send();
Pattern 2:
When fileId is the Google Docs file which are Google Document, Google Spreadsheet, Google Slides and so on, you can use the following script. The method of Files: export in Drive API is used.
Modified script:
var xhr = new XMLHttpRequest();
xhr.open('GET', 'https://www.googleapis.com/drive/v3/files/' + fileId + '/export?mimeType=application%2Fpdf');
xhr.setRequestHeader('Authorization', 'Bearer ' + token);
xhr.onload = () => {
console.log(JSON.stringify(xhr.response,true,4));
};
xhr.send();
In this case, the Google Docs file is downloaded as a PDF format. When you want to download the file as other mimeType, please set the mimeType.
Note:
In above scripts, the file is downloaded as the binary.
References:
Download files
Files: get
Files: export

Error 404 while trying to POST JSON to PHP using JS

I am setting up a server using surveyjs library and am looking to connect it to an personal database that is hosted locally,
I am having trouble going from javascript and sending the json file to php and then sending that information to the database.
Have tried to you XLMHttp code to send json file but it wont post and I am getting a 404 not found error inside of the developer tools
This is my entire js file excluding the JSON
function sendDataToServer(survey) {
survey.sendResult('b48f3bcb-3978-4486-aa30-22cf94092850');
}
var survey = new Survey.Model(surveyJSON);
$("#surveyContainer").Survey({
model: survey,
onComplete: sendDataToServer
});
survey.onComplete.add(function (sender, options) {
var xhr = new XMLHttpRequest();
xhr.open("POST", "connect.php", true);
xhr.setRequestHeader("Content-Type", "application/json; charset=utf-8");
xhr.send(JSON.stringify(sender.data));
});
This is the php file
//Decode the JSON string and convert it into a PHP associative array.
$data = json_decode($_POST['sender'], true);
This is the specific line that is causing the error
xhr.send(JSON.stringify(sender.data));

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.

jquery ajax not serving pdf file

I am trying to download a pdf file using jquery, ajax & django.
My django views.py:
if request.POST.get('action') == 'download_labels':
order_list = json.loads(request.POST.get('order_dict'), None)
PackedOrders(dbname, order_list).downloadLabels()
file = open('shipping_labels.pdf','rb')
response = HttpResponse(file, content_type='application/pdf')
response['Content-Disposition'] = "attachment; filename=shipping_labels.pdf"
os.system('rm shipping_labels.pdf')
return HttpResponse(response, content_type='application/pdf')
My ajax query:
data : {action:'download_labels',
order_dict:JSON.stringify($checkedRows)},
success : function(response, status, request) {
var file = new Blob([response], {type: 'application/pdf'});
var fileURL = window.URL.createObjectURL(file);
window.open(fileURL,'_blank');
},
The ajax returns the file as binary data response and open it in a new tab. But all I see in new tab are blank pages. The number of blank pages is equal to number of pages in original pdf file.
In Console I see this:
Error: Invalid XRef stream header
...
Warning: Indexing all PDF objects
pdf.worker.js (line 235)
<System>
PDF 85b859244e496561d60d217869d5d38a [1.3 - / -] (PDF.js: 1.3.76)
Error: Bad FCHECK in flate stream: 120, 239
...
Here is the complete log file.
I'm not a jQuery expert but I do not think jQuery ajax supports blobs. In the documentation it only lists these data types: xml, json, script, or html.
However I was able to get this functionality to work without using jQuery and using ajax with plain JavaScript with this code,
My JavaScript (I would also add error handling to this)
var xhr = new XMLHttpRequest();
xhr.open('GET', '/pdf_test', true);
xhr.responseType = 'blob';
xhr.onload = function(e) {
if (this.status == 200) {
var blob = new Blob([this.response], {type: 'application/pdf'}),
fileURL = URL.createObjectURL(blob);
window.open(fileURL,'_blank');
}
};
xhr.send();
My django view ( I would also add error handling to this)
def pdf_test(request):
pdf_file = open(r'C:\Pdfs\calculation_of_semiconductor_failure_rates.pdf', 'rb')
response = HttpResponse(pdf_file, content_type='application/pdf')
response['Content-Disposition'] = 'attachment; filename="shippinglabels.pdf"'
return response
On top of this if you don't need to open in new tab but can just download the file, then you can avoid ajax/Javascript entirely and just use HTML which is a simpler approach
<a id="pdf-test" href="/pdf_test">Download PDF</a>
For credit and further reading I used these links
jQuery Ajax
StackOverflow question
Introduction to JavaScript Blobs and File Interface

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