In order to upload a file to Backblaze B2 directly from the browser, I need to send the X-Bz-Content-Sha1 header.
This header is the SHA1 of the added file.
This is from an example using raw JS and not DropzoneJS:
const file = uploadFileInput.files[0];
const reader = new FileReader();
reader.onload = function () {
const hash = CryptoJS.SHA1(CryptoJS.enc.Latin1.parse(reader.result));
/* snip */
xhr.setRequestHeader("X-Bz-Content-Sha1", hash);
};
reader.readAsBinaryString(file);
How can I generate a SHA1 of the file I add into DropzoneJS?
Here's my DropzoneJS code:
let myDropzone = new Dropzone("#dropzone", {
acceptedFiles: "image/jpeg,image/jpg",
maxFilesize: 100,
init: function () {
this.on("addedfile", function (file) {
fetch("/api/presign-upload-url", {
headers: {
"Content-Type": "application/json",
"Accept": "application/json",
"X-Requested-With": "XMLHttpRequest",
"X-CSRF-Token": csrfToken
},
method: "post",
credentials: "same-origin",
body: JSON.stringify({
key: file.name
})
})
.then(function (response) {
return response.json();
)
.then(function (json) {
console.log(file);
// I don't know how to generate the SHA1 here, `file`
// seems like the wrong object to work with?
let hash = "2";
myDropzone.options.headers = {
"Content-Type": file.type,
"Authorization": json.upload_url.authorizationToken,
"X-Bz-File-Name": file.name,
"X-Bz-Content-Sha1": hash,
};
myDropzone.options.url = json.upload_url.uploadUrl;
myDropzone.processFile(file);
});
});
}
});
Related
I want download file on my ionic mobile app from amazon S3 but I have this issue Origin capacitor://localhost is not allowed by Access-Control-Allow-Origin.
So I add "capacitor://localhost" on my CORS configuration on amazon S3 like this :
[
{
"AllowedHeaders": [
"*"
],
"AllowedMethods": [
"HEAD",
"GET",
"PUT",
"POST",
"DELETE"
],
"AllowedOrigins": [
"*",
"capacitor://localhost"
],
"ExposeHeaders": []
}
]
but I have always the same issue.
My download function :
async downloadResource(filename: string) {
try {
this.url = this.changeSpecialCharacter(this.urlFolder + filename);
let extention = this.getFileExtension(filename);
filename = this.getFileName(filename);
if (!filename.includes(extention)) {
filename = filename + '.' + extention;
}
if (!filename) filename = this.url.split('\\').pop().split('/').pop();
const response = await fetch(this.url, {
headers: new Headers({
'Origin': 'capacitor://localhost'
}),
mode: 'cors'
});
console.log(' response '+JSON.stringify(response));
const blob = await response.blob();
const blobUrl = URL.createObjectURL(blob);
console.log(' blobUrl '+JSON.stringify(response));
const result = await Filesystem.writeFile({
path: filename,
data: blobUrl,
directory: Directory.Documents,
encoding: Encoding.UTF8
});
console.log('File written', result);
} catch (e) {
console.error('error fetch '+e);
}
}
I test also with const response = await fetch("https://file-examples.com/storage/feeb72b10363daaeba4c0c9/2017/10/file_example_JPG_100kB.jpg", {mode: 'cors'}); I have the same issue. So the problem is from the device
I tried three different methods to get checksum of a same file.
1- using crypto-js (with CryptoJS.SHA1(event.target.result))
2- using sha1.min.js (with sha1(event.target.result)
3- using crypto (with crypto.subtle.digest('SHA-1', fileUint8))
Each one produces different sha1 value for same file, I don't know why.
However, sha1(event.target.result) created same checksum as produced by online sha1 calculator. I tried all values one by one in uploading but request is failed with message 'Checksum did not match data received'
If i assume that one of sha1 value is correct, then it means there is something wrong in Uppy Uploading and the file contents are not pushed properly to bucket so error message appears in response.
.....
Here is the code sample to get sha-1.
function digestFile(file) {
var reader = new FileReader();
reader.onloadend = function (event) {
if (event.target.readyState == FileReader.DONE) {
var file_sha1 = CryptoJS.SHA1(event.target.result); // first method
var file_sha2 = sha1(event.target.result); // second method
};
reader.readAsArrayBuffer(file.data);
}
third method is here
async function digestMessage1(file) {
const fileUint8 = new TextEncoder().encode(file);
const hashBuffer = await crypto.subtle.digest('SHA-1', fileUint8);
const hashArray = Array.from(new Uint8Array(hashBuffer));
const hashHex = hashArray.map((b) => b.toString(16).padStart(2, '0')).join('');
return hashHex;
}
function digestFile(file) {
var reader = new FileReader();
reader.onloadend = function (event) {
if (event.target.readyState == FileReader.DONE) {
digestMessage1(event.target.result)
.then((digestHex) => console.log(digestHex));
};
reader.readAsArrayBuffer(file.data);
}
..
Here is the Uppy JS code.
let data = this.el.dataset;
var uppy = new UppyLib({
autoProceed: true,
allowMultipleUploadBatches: true,
restrictions: { allowedFileTypes: ['image/*', '.jpg', '.jpeg', '.png', '.gif'] }
})
uppy.use(Uppy.Dashboard, { target: '#drag-drop-area', inline: true, width: 750, height: 550})
uppy.use(AwsS3, {
getUploadParameters(file) {
return fetch('/assets/new', {
method: 'GET',
headers: { accept: 'application/json', 'content-type': 'application/json' }
}).then((response) => {
return response.json()
}).then((data) => {
return {
method: 'POST',
url: `${data.url}`,
fields: [],
headers: {
"Content-Type": "b2/x-auto",
"Authorization": `${data.token}`,
"X-Bz-File-Name": `assets/${Date.now()}-${encodeURI(file.name)}`,
"X-Bz-Content-Sha1": "94d2ff39a524e0cf20f3bd6cf909c426"
},
}
})
}
})}
I am trying to integrate a POST API call from a lambda function using Node.js 12.x.
I tried like below:
var posturl = "My post api path";
var jsonData = "{'password':'abcdef','domain':'www.mydomain.com','username':'abc.def'}";
var req = require('request');
const params = {
url: posturl,
headers: { 'jsonData': jsonData }
};
req.post(params, function(err, res, body) {
if(err){
console.log('------error------', err);
} else{
console.log('------success--------', body);
}
});
But when I am execute it using state machine, I am getting the below exception:
{
"errorType": "Error",
"errorMessage": "Cannot find module 'request'\nRequire stack:\n- /var/task/index.js\n- /var/runtime/UserFunction.js\n- /var/runtime/index.js",
"trace": [
"Error: Cannot find module 'request'",
"Require stack:",
"- /var/task/index.js",
"- /var/runtime/UserFunction.js",
"- /var/runtime/index.js",
" at Function.Module._resolveFilename (internal/modules/cjs/loader.js:815:15)",
" at Function.Module._load (internal/modules/cjs/loader.js:667:27)",
" at Module.require (internal/modules/cjs/loader.js:887:19)",
" at require (internal/modules/cjs/helpers.js:74:18)",
" at Runtime.exports.handler (/var/task/index.js:8:14)",
" at Runtime.handleOnce (/var/runtime/Runtime.js:66:25)"
]
}
Here the posturl is my api path and jsondata is my key value pair data.
So How can I call a POST API from lambda function? How can I pass the entire jsondata key when call API? How can I parse the response after the service call?
Update: I have tried like below
All my details are passing with a key jsonData, where I can specify that? Without that key, it will not work.
exports.handler = (event, context, callback) => {
const http = require('http');
const data = JSON.stringify({
password: 'mypassword',
domain: 'www.mydomain.com',
username: 'myusername'
});
const options = {
hostname: 'http://abc.mydomain.com',
path: 'remaining path with ticket',
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Content-Length': data.length
}
};
const req = http.request(options, (res) => {
let data = '';
console.log('Status Code:', res.statusCode);
res.on('data', (chunk) => {
data += chunk;
});
res.on('end', () => {
console.log('Body: ', JSON.parse(data));
});
}).on("error", (err) => {
console.log("Error: ", err.message);
});
req.write(data);
req.end();
};
source : How to Make an HTTP Post Request using Node.js
const https = require('https');
const data = JSON.stringify({
name: 'John Doe',
job: 'Content Writer'
});
const options = {
hostname: 'reqres.in',
path: '/api/users',
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Content-Length': data.length
}
};
const req = https.request(options, (res) => {
let data = '';
console.log('Status Code:', res.statusCode);
res.on('data', (chunk) => {
data += chunk;
});
res.on('end', () => {
console.log('Body: ', JSON.parse(data));
});
}).on("error", (err) => {
console.log("Error: ", err.message);
});
req.write(data);
req.end();
I am using formData to POST an image I uploaded via ImagePicker. I am sending the parameters like so:
let formData = new FormData();
formData.append('image', { uri: localUri, name: filename, type });
formData.append('description', 'this is the decription');
return await fetch('https://prana-app.herokuapp.com/v1/visions/', {
method: 'POST',
body: formData,
header: {
'Accept': 'application/json',
'Content-Type': 'application/json',
'X-User-Email': this.state.email,
'X-User-Token': this.state.accessToken
},
});
};
This doesn't seem to work, as I am getting a very generic NoMethodError (undefined methodbuild' for nil:NilClass):` error.
How can I POST my parameters in the correct way given that the image parameter is an image and the description parameter is a string?
Thanks
Content-Type must be different when using Formdata.
example.js:
fileSend = () => {
const apiUrl = "http://00.000.00.000:0000/upload";
const uri = this.state.image;
const stringdata = {
username: this.state.name,
introduce: this.state.introducetext,
addresstext: this.state.addresstext
};
const uriParts = uri.split(".");
const fileType = uriParts[uriParts.length - 1];
const formData = new FormData();
formData.append("userfile", {
uri,
name: `photo.${fileType}`,
type: `image/${fileType}`
});
for (var k in stringdata) {
formData.append(k, stringdata[k]);
}
const options = {
method: "POST",
body: formData,
headers: {
Accept: "application/json",
"Content-Type": "multipart/form-data"
}
};
return fetch(apiUrl, options)
As shown in the example above, Content-Type should write multipart/form-data and pass it over to For ... in if Stringdata is not one.
If I use the library #microsoft/microsoft-graph-client, I can get the contact photo as binary data, convert it to base64 and get the correct photo with the code below:
const request = require('request')
const microsoftGraph = require('#microsoft/microsoft-graph-client');
let token = token-value
let client = getMicrosoftGrapClient(token);
let id = contact-id;
let url = '/me/contacts/' + id + '/photo/$value';
client.api(url).get().then((res) => {
//console.log(res);
var encodedImage = new Buffer(res, 'binary').toString('base64');
console.log("encodedImage>>>>>>>>>>>>>>>>>>>>>>")
console.log (encodedImage);
}).catch((err) => {
console.log(err);
});;
function getMicrosoftGrapClient (token) {
// Create a Graph client
return microsoftGraph.Client.init({
authProvider: (done) => {
// Just return the token
done(null, token);
}});
}
I cannot get the correct contact photo with the HTTP GET. The HTTP
response code is 200 but the body is not the binary data of photo.
Please let me know what the error is. Here is the code:
const request = require('request')
request({
url: "https://graph.microsoft.com/v1.0/me/contacts/{contact_id}/photo/$value",
method: 'GET',
headers: {
'content-type': 'image/jpg',
'Authorization': 'Bearer {token}'
}
}, function (error, response, body){
console.log(error);
var encodedImage = new Buffer(body, 'binary').toString('base64');
console.log(encodedImage);
});
Encoding needs to be explicitly specified as
encoding: null
In that case the body will be of type Buffer, instead of the default (string).
And content-type could be omitted.
Example
request({
url: "https://graph.microsoft.com/v1.0/me/photo/$value",
method: 'GET',
encoding: null,
headers: {
'Authorization': 'Bearer ' + accessToken,
}
}, function (error, response, body) {
var encImage = new Buffer(body, 'binary');
fs.writeFileSync(filePath, encImage );
});