Checksum Error while uploading files to BackBlaze (B2) using Ajax request - ajax

I have spent an awful lot of time trying to upload files to b2 using clientside ajax requests (vue-dropzone.js), and even though I supplied the file's valid sha1 checksum, the b2 server still responds with "checksum did not match data received" with status code 400. I've checked and rechecked the checksums with all the tools I have and I'm still not able to trace the source of the error. Its as if something happens to the file while its in transit or something.
I've uploaded the same files using the command line tool and it works fine but when I upload via ajax using the exact same sha1 checksum it doesn't work.
My questions are:
Does b2 even allow file uploads through ajax?
If it does allow uploads via ajax then what am i doing wrong?
Does the files remain valid when uploaded using "X-Bz-Content-Sha1", " do_not_verify". Cause I've tried that only to get invalid files when I downloaded them back.
Are there other things I need to know about uploading files to b2 using ajax requests
Please view my ajax codes see if I got anything wrong:
sending(file, xhr, formData) {
// This function runs for each file right before they are sent by dropezone.
// This is a good opportunity to insert file specific values
// in this case the file's upload url, name and auth token
let fileName = '';
console.log('this is file type', file.type);
if (file.type.includes('image')) {
fileName = 'images/${uuid.v1()}.png';
} else if (file.type.includes('video')) {
fileName = 'videos/${uuid.v1()}.${file.type.split(' / ')[1]}';
}
const url = appConfig.serverAddress + '/catalog/submitFiles';
console.log('this is sha1_hash', this.uploadInfo.sha1_hash);
// open the xhr request and insert the file's upload url here
xhr.open('Post', this.uploadInfo.url, true);
// set b2's mandatory request headers
// xhr.setRequestHeader(
// 'Authorization',
// 'Bearer ' + store.getters.getUserIdToken,
// );
xhr.setRequestHeader('Authorization', this.uploadInfo.authorizationToken);
xhr.setRequestHeader('X-Bz-Content-Sha1', this.uploadInfo.sha1_hash);
xhr.setRequestHeader('X-Bz-File-Name', fileName);
xhr.setRequestHeader('Content-Type', 'b2/x-auto');
formData = new FormData();
formData.append('files', file);
// the rest will be handled by dropzones upload pipeline
}

You are sending the file using form encoding, which causes the SHA-1 validation to fail since B2 is expecting the raw file data, with no encoding. The doc for b2_upload_file says:
The file to be uploaded is the message body and is not encoded in any way. It is not URL encoded. It is not MIME encoded.
I'm not an expert on vue-dropzone, but I'm guessing you need to just delete the two lines referencing formData. It looks like the default upload pipeline will send the raw file content.

Related

streaming pdf files in datapower gateway

i want to download a pdf which is present in datapower local directory
i created a serice and wrote a small gateway script but the pdf in downloading in unreadable format
i want the pdf to be downloaded in .pdf format
var urlopen = require('urlopen');
var fs = require('fs');
urlopen.open("local:///pdf.pdf", function (error, response) {
if (error) {
session.output.write("openCallback error: " + error.errorMessage+"\n");
}
else {
if (response.statusCode == 200) {
// You have a 200, so you can read the file
fs.readFile("local:///pdf.pdf", function(error,data) {
session.output.write(data);
});
}
}
});
Well, first of all, you are reading the the PDF twice with your code, you should use either urlopen, or fs.readFile, but not both...
Make sure that your PDF is downloadable and readable if you download it directly from the file-system (through the UI) to make sure that it has not been "destroyed" while adding it to the DP box.
Secondly, it's always safer to store the PDF as base64 so if you can alter the way the PDF is added, encode it to base64 prior to saving it, then fetch the base64 and decode it just prior to returning it.
You must include the content-type for PDF, "application/pdf", in the response, else DataPower will return it as XML (which is the default), so add a response header for content-type: application/pdf.
I am a bit uncertain if DataPower can handle "application/PDF" (don't remember) but as long as it's not XML or JSON it shouldn't touch it...
Else try with "application/octet-stream" if PDF doesn't work.

Using http.GetFile how to prevent bad url requests from creating new files

I am using the http.getFile function to download files from an api. I am having a issue where files are still created, even though the url passed to getFile is invalid or returning errors. After some research it appears the getFile will always create a new file, is there a way to prevent getFile from creating a new file if the url is invalid?
The only work around I can think is to check the file size after calling the getFile and deleting it if there is no data?
In the example below I was tying to use the File.exists, but it always returns true.
return http.getFile(fullUrl, filePath)
.then(function(r){
// Test - Check if file Exists
console.log("Check File Exist: " + fs.File.exists(filePath));
}, function(error) {
});
Just check if the "fullUrl" is a valid url before requesting:
var regexp = /(ftp|http|https):\/\/(\w+:{0,1}\w*#)?(\S+)(:[0-9]+)?(\/|\/([\w#!:.?+=&%#!\-\/]))?/
var isUrlValid = regexp.test(fullUrl);
if(isUrlValid){
http.getFile(fullUrl, filePath)
}

AJAX Query Not Working After Move to AWS $ CloudFront

After a long time lurking, its time to ask my first question...
I'm having trouble with an AJAX query that used to work prior to moving to AWS.
Previously, My web site was hosted on a WAMP server for testing and development and the following relevant code worked fine.
//Read XML file from disc and send file content to other functions\\
function Get_XML_File(){
var XML_File_Path = File_Path + Client_Code + '/' + ID + '/' + ID + '_Analysed_Wave.web'
var xhttps = new XMLHttpRequest();
xhttps.onreadystatechange = function() {
if (xhttps.readyState == 4 && xhttps.status == 200){
Read_Meta_Data(xhttps)
Read_Time_Status(xhttps)
Read_Wave_Height(xhttps)
;}
};
xhttps.open("GET", XML_File_Path, true);
xhttps.send();
}
//Extract Header Data from XML file\\
function Read_Meta_Data(xml) {
var xmlDoc = xml.responseXML;
// Client//
var Client_ID = xmlDoc.getElementsByTagName('Client_ID')[0].childNodes[0]
var Client_Name = xmlDoc.getElementsByTagName('Client_Name')[0].childNodes[0]
Recently, This site was moved to a Elastic Beanstalk distribution with AWS.
'www.atmocean.com.au' has been provisioned with an SSL certificate using the AWS certificate manager.
'assets.atmocean.com.au' is also covered by an SSL certificate and is mapped to a cloudfront distribution of a S3 bucket.
Within the S3 bucket are xml formatted files with a .web suffix (these are generated by proprietary software.)
When the relevent web page is viewed, the chrome console shows the following error: "Uncaught TypeError: Cannot read property 'getElementsByTagName' of null"
this error is in reference to this line:
var Client_ID = xmlDoc.getElementsByTagName('Client_ID')[0].childNodes[0]
What I can't understand is that when the 'Network' tab of the developer console is viewed, the resource is shown as correctly loaded with a status code of 200.
Further, the file content can be viewed in the 'response' tab.
Does this mean that the file has been correctly downloaded from the server to the client?
If so, why does code that formerly worked without error now fail to get the file content?
Does something other than a standard website configuration need to be provisioned through elastic beanstalk (or other means)?
Thanks in anticipation.
You receive a HTTP 200 meaning the server understand the request and can full-fill the request but then it delivers the content, when you execute Read_Meta_Data it does not mean the full content has been delivered
you could add a console.log(xml) and console.log(xmlDoc) to see the current content of your progress
what I would suggest you leverage your code to add a listener on the completion of the transfer
var xhttps = new XMLHttpRequest();
xhttps.overrideMimeType('text/xml');
xhttps.addEventListener("load", transferComplete, false);
function transferComplete(evt) {
// from here your transfer has been completed
}
note: there's also a loadend method which runs when the load has been completed (wether it has been successful or not - never used it)
Frederic,
Thanks for your response.
The clue was in the following line:
xhttp.overrideMimeType('text/xml');
because the xml files use a custom file extension it was being returned as a text string.
I've changed the function to now read as follows:
//Read XML file from disc and send file content to other functions\\
function Get_XML_File(){
var XML_File_Path = File_Path + Client_Code + '/' + ID + '/' + ID + '_Analysed_Wave.web'
var xhttp = new XMLHttpRequest();
xhttp.overrideMimeType('text/xml');
xhttp.onreadystatechange = function() {
if (xhttp.readyState == 4 && xhttp.status == 200){
Read_Meta_Data(xhttp)
Read_Time_Status(xhttp)
Read_Wave_Height(xhttp)
;}
};
xhttp.open("GET", XML_File_Path, true);
xhttp.send();
}
xhttp.overrideMimeType('text/xml');
And with that one change, all is well with the world. (well my function at least.)

Cordova/Phonegap How to write a PNG file to Filesystem?

This question goes for mp3 and wav files as well.
I have set up an express.js server which basically sends the required files as follows:
res.sendFile('someImage.png', {root: './images'});
Then on the client-side, I receive the image with:
var req = new XMLHttpRequest();
...
req.onreadystatechange = function(e) {
if(req.readyState != 4) return;
...
writeMyFile(null, e.target.response, someCallback);
}
...
So in the response I do have my file. I want to write this file in to my local filesystem. I implement write as follows:
var writeMyFile = function(err, file, someCallback) {
this.dir.getFile('myImages/someImage.png', {create: true}, function(fileEntry) {
fileEntry.createWriter(function(fileWriter) {
var blob = new Blob([file], {type: 'image/png'});
fileWriter.write(blob);
}, someCallback);
}, someCallback);
};
After executing these, I see a png file is created in myImages folder. It is however twice the size of the original file, and it is considered as corrupted by the operating system. Preview cannot view the image. Same goes for mp3/wav files as well, they are twice the size and won't play on any players and etc..
What am I doing wrong here? How can I write those files into filesystem appropiately?
The code above works perfectly when files are json objects. We suspect there might be an encoding problem, but no idea for fixes so far.
Finally, I am using the closure compiler.
Thanks for your help.
After sleeping on the problem, I found out the solution which was incredibly simple. So here it is for future reference.
On Xhr Request, make sure to set the responseType to arrayBuffer or blob before sending the request. In my case it is arrayBuffer because I already had a blob builder which would act on the data received. That is:
...
req.responseType = 'arraybuffer';
req.onreadystatechange = ...
req.send();
It turns out that Mime Type in blob construction won't affect these binary files to be written. In my case, I could store mp3 songs perfectly where I had their MIME as: 'image/png'. However I am not sure if this has other implications, I am just simply saying that the files worked ok no matter which type I had set.

html5 multiple upload along with ajax

I am trying to use the multiple upload attribute of HTML5 to upload files.
I know it wouldn't work with IE and fall back to single file upload.
also I found some invalid html tag like min max allows opera to do the same.
I am trying to do the following:
The browse button be capable of selecting multiple files.
But the ajax should send files one by one.
My scenario is something like this:
the user selects 5 files and starts the upload . Now the ajax should firstfile send the first file, then second, and so on.
The server side script does something with the file and returns some data.
now as soon as one file upload is completed it must render that part of the result.
So as the user selects images and starts uploading the results come out as soon as each file is uploaded (and not after all the files are uploaded).
I tried something like this :
function handleFiles(files)
{ alert(files.length); //properly returns the number of files selected
for (var i = 0; i < files.length; i++) {
new FileUpload(files[i])
}
}
function FileUpload(file) {
var reader = new FileReader();
var xhr = new XMLHttpRequest();
this.xhr = xhr;
xhr.open("POST", "portfolio/add_media");
reader.onload = function(evt) {
xhr.sendAsBinary(evt.target.result);
};
reader.readAsBinaryString(file);
}
after reading the tutorial at mozilla but I end up with missing params.
. so can some one suggest me a clean solution to this
Some more details :
When I pass a single file ( with no multiple attribute ) my server recieves :
"image"=>[# < ActionDispatch::Http::UploadedFile:0x10d55be8
#tempfile=#< File:C:/Users/Gaurav/AppData/Local/Temp/RackMultipart20110701-1916-2ly4k2-0>,
#headers="Content-Disposition:
form-data; name=\"picture[image][]\";
filename=\"Desert.jpg\"\r\nContent-Type:
image/jpeg\r\n",
#content_type="image/jpeg",
#original_filename="Desert.jpg">]}}
But when I use multiple attribute and send using xhr I am able to get only one file param. How do I get the rest of the params ? esp the action dispatch thingy
You are simply sending the file data to the server, without encoding it in any way. For the server to know how to process it you need to encode your data properly (multipart/form-data encoding). Easiest way is using a FormData object: https://developer.mozilla.org/En/Using_XMLHttpRequest#Sending_files_using_a_FormData_object. Only that instead of data.append("CustomField", "This is some extra data") you would write data.append("file1", event.target.result).

Resources