I'm working into a project to encrypt/decrypt files in JavaScript. To save the encrypted/decrypted file in disk, I'm using blob. All the process is working, the files get encrypted (and some tests show-me that decrypted too) correctly. And I can save even large files with the blob method (I was using URI data before, and it was causing browser crash errors when files size more than 1MB). But for some reason, I can't save the decrypted blob content into a file correctly. When it's a TXT file, I get this in the beginning of the file content:
data:text/plain;base64,
and it continues with the text content encoded in base64. I need it to be saved as original file, not in base64. When I decrypt an exe file, it's corrupted, so if I open it into some text editor, I get:
data:application/x-msdownload;base64,
Again, looks like the file is getting saved in base64 and with this header attached. Here's my code to create/save the content of blob (on decrypt routine):
reader.onload = function(e){
var decrypted = CryptoJS.AES.decrypt(e.target.result, password)
.toString(CryptoJS.enc.Latin1);
var blob = new Blob([decrypted]);
var objectURL = window.URL.createObjectURL(blob);
if(!/^data:/.test(decrypted)){
alert("Invalid pass phrase or file! Please try again.");
return false;
}
a.attr('href','' + objectURL);
a.attr('download', file.name.replace('.encrypted',''));
step(4);
};
reader.readAsText(file);
}
How can I save the files with the original content? And not header+base64 encode?
Related
Working on a Javascript-based file encryption program. It works great for text files, but I'm trying to do other data (images, etc) and the decrypted file isn't matching. In my program, I use the following code to read the file that the user provides:
let reader = new FileReader();
let file = UI.file.input.files[0];
reader.readAsText(file, 'UTF-8');
The reader then adds that to a Javascript object that contains other information, like the date and file name. Then, that's stringified using JSON.stringify() and encrypted. When the encryption is completed, the file gets saved as a different file format with the encrypted JSON inside of it. The code for that is:
let message = // ENCRYPTED FILE STRING
let file = new Blob([message], {
type: 'text/plain'
});
let url = URL.createObjectURL(file);
The url is then attached to a link element on the page. That's all working fine.
To decrypt it, the file is again provided by the user and runs through the same reader as used above. It's decrypted successfully and the resulting string is again put into an object using JSON. Up to that point, it works exactly as it's supposed to. It works fine if what I'm decrypting is a text file, but if I do an image file it all goes bad.
To save the decrypted file, I use this code:
let message = // DECRYPTED DATA CONVERTED TO AN OBJECT
let fileName = message.name;
let fileType = message.type;
let file = new Blob([message.data], {
type: fileType
});
let url = URL.createObjectURL(file);
The original file and and original file type are both pulled from the file before it's encrypted and added to the object that has the file data. Like I said, there's no problem with the encryption or decryption process. I've used a HEX viewer to check and the string that is being put into the encryption process is identical to the one coming out. I'm guessing the issue is somewhere in my final block of code.
My best guess is something to do with encoding, although I'm not sure exactly what. Any help would be greatly appreciated.
You can use FileReader.readAsDataURL and strip the data:*/*;base64, from the string. Then you'll have a base64 encoded string that you can put into JSON.
I try to download a pdf file that has been previously encoded using base 64.
I try to download it from an anchor tag, as follows
Download;
The file is downloaded but when I try to open it I get a message that the file has damage or is corrupted.
Interestingly, if I change href to an encode image data, the file is downloaded and opened as expected.
I found this example http://jsfiddle.net/filixix/0816jdfq/ and I see that is changed from data:application/pdf;base64, to data:application/octet-stream;base64, I tried but I am getting the same result.
Update
I am encode the pdf file as follows
const element = document.querySelector('#file'); // input type file
element.addEventListener('change', handleChange);
function handleChange() {
const file = this.files[0];
const fileReader = new FileReader();
fileReader.onload = function() {
const data = this.result;
// store data in database in a text type field
};
fileReader.readAsDataURL(file);
}
hen, in the view where I want to download the file, I realize the logic that I commented
General idea works as expected.
But I recommend You to keep pdf as file.
Cause Your corrupted pdf issue may be because of db field size (if You keep that string in db) or browser's request url limitations
So You're saying:
store data in database in a text type field
If You don't plan to move to file storage just change field type to: LONGBLOB
I've seen SO questions similar to my use case w/ angular and other server side platforms but not for pure javascript.
I have an app where I do a $.ajax and do a get call to an API, which returns a previously converted excel file (excel to base64); I need to re-convert this base64 data back into it's original form - i.e. into Excel file. I tried retracing the steps I took to convert the excel into base64, reversing some of them, but I'm not able to generate the original file. An excel file IS being generated, but it still has base64 data and therefore opens w/ errors and in a corrupted state.
Has anyone else successfully done this?
Below is my code and fiddle link: (I didn't add the base64 json data (responseData) here since it's large, but it's on the fiddle)
var bindata = window.atob(responseData);
function DownloadExcel() {
window.location.href = "data:application/vnd.ms-excel;base64, bindata"
}
var blob = new Blob([responseData], {type: 'application/vnd.ms-excel'});
if (window.navigator && window.navigator.msSaveBlob) {
window.navigator.msSaveBlob(blob);
}
else {
var objectUrl = URL.createObjectURL(blob);
window.open(objectUrl);
}
jsfiddle link: https://jsfiddle.net/damon_matt/2ofz6xrd/
I would like to be able to edit a file that has been selected for upload. I want to search and replace text in case absolute files should be made relative...
I notice in the File API I can do some of it, but I get a little stuck:
document.getElementById('exampleInputFile').onchange = function(event) {
var fileToLoad = event.target.files[0];
if (fileToLoad) {
var reader = new FileReader();
reader.onload = function(fileLoadedEvent) {
var textFromFileLoaded = fileLoadedEvent.target.result;
//Use logic to remove absolute files
//Upload S3
};
reader.readAsText(fileToLoad, 'UTF-8');
}
};
I am trying to figure out how now to convert that text to a proper File so that I can upload it to S3 using an existing api that expects something returned by: event.target.files[0] code above.
I do not want the server to handle any heavy lifting here if I can avoid it (files can easily be a few megabytes since they can be 3D models).
Assuming you know the url of the file when it lands in the S3 bucket, you can retrieve the file using a http.get, which will give you the contents of the (I assume plain text file). You can then parse that file and do whatever modification you need to do on the contents. If the file has changed, you can then write it back to the S3 bucket to replace the original file.
On AWS you can use Lambda to execute NodeJS code when an event is triggered (for example an upload to a specified bucket).
I have a base64 string, file type. File type can be image, text or even pdf. I need to show download link and when user clicks it should start downloading as expected file.
Concisely, server sends me file as base64 string, and I need to save it as file on browser. How can I save base64 string as file on browser? It would be best if solution works on IE9 also.
You can use download.js.
download(base64String, filename, mimeType)
Adapted from https://gist.github.com/RichardBray/23decdec877c0e54e6ac2bfa4b0c512f to work on Firefox.
function downloadBase64File(contentBase64, fileName) {
const linkSource = `data:application/pdf;base64,${contentBase64}`;
const downloadLink = document.createElement('a');
document.body.appendChild(downloadLink);
downloadLink.href = linkSource;
downloadLink.target = '_self';
downloadLink.download = fileName;
downloadLink.click();
}
You can do this from js to download pdf.
Use:
document.location = 'data:application/pdf;base64,' + base64String
You get the effect you desire (web page showing a link, and when user clicks, the save as dialog pops up) when the appropriate response headers are present when the browser requests the resource:
Content-Disposition: attachment; filename="yourfilename.extension"
If you're getting the file from the server as a base64 string embedded in your html, perhaps you can skip the embedding and simply embed a direct link to the file on your server, having the server serve it up to the user.
Related SO on Content-Disposition