How to send both text and binary data in axios post request? - javascript

I would need to find a solution to send via a single axios POST request both of the following:
json structure
binary file (excel file)
How can I achieve this?
let files = event.target.files;
const fileReader = new FileReader();
fileReader.readAsText(files[0], null);
fileReader.onload = () => {
this.fileContent = fileReader.result;
let binaryDataForObject = this.fileContent;
let referenceDataStructure = {
textData: textDataForObject,
binaryData: binaryDataForObject,
referenceDataFileExtension: this.referenceDataFileExtension,
userProvidedDataTypes: this.columnTypes
};
}
this.axios
.post(
"http://url,
referenceDataStructure
)
This works technically but on the java side I couldn't figure out, how to decode the binary data (encoded as a string) so that it is treated as an excel file.
Thank You in advance for any meaningful responses.
Lubos.

With simple POST request you can send only up to 1mb of binary data
To send binary and text in one request you should use FormData
Check out this answer for information
Update 14.12
How I managed to do this in my recent project was using FormData
So firstly you need to get file as a blob:
const fileReader = new FileReader()
// Here we will get the file as binary data
fileReader.onload = () => {
const MB = 1000000;
const Blob = new Blob([fileReader.result], {
// This will set the mimetype of the file
type: fileInputRef.current.files[0].type
});
const BlobName = fileInputRef.current.files[0].name;
if (Blob.size > MB) return new Error('File size is to big');
// Initializing form data and passing the file as a param
const formData = new FormData();
// file - field name, this will help you to read file on backend
// Blob - main data to send
// BlobName - name of the file, default it will be name of your input
formData.append('file', Blob, BlobName);
// Append json data
formData.apped('some-key', someValue)
// then just send it as a body with post request
fetch('/api/submit-some-form-with-file', {
method: 'POST',
body: formData
})
// Handle the rest
.then()
}
fileReader.readAsArrayBuffer(fileInputRef.current.files[0])
You can wrap this example in handle submit function in react and like or use it as is

Related

pdf.js get password-protected file content

I want to retrieve the content of a password-protected file as a File object using PDF.js library.
I tried to get the raw data from the promise and convert it to a File. However the file is still encrypted.
Here is a sample of code:
const loadingTask = pdfjsLib.getDocument(file);
loadingTask.onPassword = (callback, reason) => {
callback(password);
};
loadingTask.promise.then((pdfDocument) => {
//Here I tried to retrieve data from `pdfDocument` but it is still encrypted
const data = await pdfDocument.getData(); //The data is still encrypted
const blob = new Blob([data]);
const pdfFile = new File([blob], 'name', { type: 'application/pdf' });
});
Is there a way with PDF.js library to get the decrypted PDF as a File object ?
Thanks in advance.

Convert input files to byte[] javascript

I'm working on a REST web application that manages documents between users and uploaders. The backend is written in Java and my Document entity contains, besides various attributes, a byte[] content. I was able to send a file created at server side by
#GET
...
document.setContent(Files.readAllBytes(Paths.get("WEB-INF/testFile.txt")));
return Response.ok(document).build();
and retrieve it at front-end (vueJs) through
async function download(file) {
const fileURL = window.URL.createObjectURL(new Blob([atob(file.content)]));
const fileLink = document.createElement("a");
fileLink.href = fileURL;
fileLink.setAttribute("download",`${file.name}.${file.type}`);
document.body.appendChild(fileLink);
fileLink.click();
fileLink.remove;
window.URL.revokeObjectURL(fileURL);
}
the problem is that when I try to upload a file and then download it, its content is not parsed correctly (is shown undefined, string in Base64 or numbers depending on how I try to solve it). The file is sent by a post request and is retrieved through an input form bound to an onFileSelected function.
function onFileSelected(e) {
var reader = new FileReader();
reader.readAsArrayBuffer(e.target.files[0]);
reader.onloadend = (evt) => {
if (evt.target.readyState === FileReader.DONE) {
var arrayBuffer = evt.target.result;
this.file.content = new Uint8Array(arrayBuffer);
//this.file.content = arrayBuffer;
}
};
}
axios.post(...,document,...)
and I have tried using atob and btoa as well before assigning the value to this.file.content. If I print the file on server Welcome.txt it gives B#ae3b74d and if I use Arrays.toString(welcome.getContent()) it gives an array of numbers but as soon as it passed to the frontend its content become in Base64 welcome: { ... content: IFRoaXMgaXMgYSB0ZXN0IGZpbGUhIAo...}. Any idea? Thank you a lot!

Converting dataURI to file for upload via REST does not work but normal filefield upload works fine

I have implemented a solution that accepts a single file upload (image for profile) in a Django Rest Framework backend. This route api/people/id/upload_image. Only accepts a parameter with an image. and can be used via HTTP POST.
When uploading via a fileinput field in eg. Postman, the default Django API or via browser fetch() in my Vue.js application is no problem. So it seems as long as it is a default form-upload field it is doing its job.
But in my frond-end (vuejs 3) I am using an image-cropper. Users can upload an image and via the javascript cropper the image can be cropped. This is important for the UI because I need a square image. The cropper uses HTMLCanvasElement.toDataURL() as export format.
And what seemed to be not that difficult gets me stuck for days now. I just can't find a way to convert and POST the cropped image in such a way that is accepted by the upload_image API backend. I am using Fetch() for sending this POST call.
I am not a javascript expert so I get my knowledge via internet and I tried it in several ways; with first creating a BLOB from the dataURI, and by creating a File before feeding it to dataForm and send it as :body in Fetch()
The dataURI seems OK because I am also replacing the cropped image directly in the HTML. And that looks totally fine. The API is responding with an 'HTTP 200 OK'. But the old image is not being replaced.
So my assumption is that there is something wrong with the image send to the API, because via normal fileupload everything works fine. How should I convert this dataURI in a proper way so it can be send and accepted by the API endpoint. And how should the API call look like: headers, body..
this is my last attempt in converting and sending the cropped image: (dataURIimage is OK)
uploadPhoto(context, dataURIimage) {
const blob = dataURItoBlob(dataURIimage);
const resultFile = new File([blob], "picture", {
type: "image/png"
});
const formData = new FormData();
formData.append("image", resultFile);
const headerToken = "Token" + " " + this.getters.getToken;
const url =
"https://workserver-7e6s4.ondigitalocean.app/api/people/" +
this.getters.getProfiel.id +
"/upload_image/";
fetch(url, {
method: "POST",
headers: {
'Content-Type': 'multipart/form-data',
'Authorization': headerToken,
},
body: formData,
})
.then(function(response) {
console.log(response.status)
if (response.ok) {
return response.json();
}
})
.then(function(data) {
console.log(data.image);
})
.catch(function(error) {
alert(error + " " + ":ERROR");
});
},
function dataURItoBlob(dataURI) {
// convert base64 to raw binary data held in a string
// doesn't handle URLEncoded DataURIs - see SO answer #6850276 for code that does this
var byteString = atob(dataURI.split(',')[1]);
// separate out the mime component
var mimeString = dataURI.split(',')[0].split(':')[1].split(';')[0];
// write the bytes of the string to an ArrayBuffer
var ab = new ArrayBuffer(byteString.length);
var ia = new Uint8Array(ab);
for (var i = 0; i < byteString.length; i++) {
ia[i] = byteString.charCodeAt(i);
}
return new Blob([ab], { type: mimeString });
}
Martijn dekker

How to convert base64 content to file object in client side and send it to controller

I am using the following code to send a list of files to the backend:
var formdata = new FormData();
if(fileObjectList.length>0){
Object.keys(fileObjectList).forEach(i => {
formdata.append('file' + i, fileObjectList[i]);
});
}
formdata.append('requestModel', JSON.stringify(request));
req.open("POST", 'contorller');
req.send(formdata);
The controller converts the file to base64 data.
To send the data via email, we have to attach the content as base64,
which I again send to the controller as a file object.
You can use jszip to add files in a zip and send whole doc as base64 in single request. check the below link for more information jszip
var jszip = new ZipHandler;
var formdata = new FormData();
if(fileObjectList.length>0){
Object.keys(fileObjectList).forEach(i => {
jszip.addFile(`${fileObjectList[i]}.fileTypeExt`, '(buffer|base64)');
});
};
var zipcomplete = await t.generate({
base64: !0,
compression: "DEFLATE"
});
formdata.append('fileDataZip', zipcomplete);
formdata.append('requestModel', JSON.stringify(request));
req.open("POST", 'contorller');
req.send(formdata)
by using C# use below code to save base64 file
System.IO.File.WriteAllBytes("/fileDataZip.zip", Convert.FromBase64String(fileDataZip));
By using nodejs utilize the below code to save base64 file
require("fs").writeFile("fileDataZip.zip", fileDataZip, 'base64');

Read downloaded blob from dropbox API using HTTP

Using dropbox you can create a shortcut by dragging and dropping a URL into your Dropbox folder. This will be saved like this:
Using the /2/files/download HTTP API from dropbox will return an XHR response that looks something like this:
How do you parse this response so that you can grab only the URL and make that a clickable link?
Here is what needs to go into an Angular 1 factory. To use this, you would just call the downloadFile function from a controller and provide the path to the file in your dropbox account.
function downloadFile(filePath) {
if (!filePath) {
console.error('Cannot download file because no file was specified.');
return;
}
return $q(function(fulfill, reject) {
$http({
url: 'https://content.dropboxapi.com/2/files/download',
method: 'POST',
headers: {
'Authorization': 'Bearer {{access-token-goes-here}}',
'Dropbox-API-Arg': `{"path": "${filePath}"}`
},
responseType: 'blob'
}).then(
results => {
// data received from dropbox is binary data saved as a blob
// The FileReader object lets web applications asynchronously read the contents of files
// https://developer.mozilla.org/en-US/docs/Web/API/FileReader
var fileReader = new FileReader();
// function will run after successfully reading the file
fileReader.onload = function() {
var string = this.result; // store the file contents
string = encodeURI(string); // get rid of the paragraph return characters
var endPosition = string.indexOf('%0D%0A', 32); // find the end of the URL, startPosition is 32
var actualURL = string.substring(32, endPosition); // grab only the characters between start and end positions
fulfill(actualURL);
};
fileReader.readAsText(results.data);
},
error => reject(error));
});
}

Categories