I'm extracting some data from an InDesign INDD file using a script. I'd like to save my data in a txt or json file, but my file is not saving successfully.
var data = 'string of data';
var filename = 'CS111.json';
var file = new File(filename);
var path = file.saveDlg(); //returns a valid path, but with spaces as '%20'
file.changePath(path);
var write = file.write(data); //returns false
file.close();
What am I missing here? The file doesn't show up in the chosen folder.
There are at least four steps in saving a file using InDesign Javascript: get a path and filename, create a file object, open the file, write to the file, and close the file.
I find that the write step will sometimes fail if I don't set the encoding.
//Define path and file name
var path = '~/Documents/';
var filename = 'filename.txt';
//Create File object
var file = new File(path + filename);
file.encoding = 'UTF-8';
file.open('w');
file.write('data here');
file.close();
Documentation: File class, .open(), .write()
Related
What I want to do: I have on the server side a file 'test_download.xlsx', and want to send it to the client side so that I can apply XLSX.read() on the retrieved object.
So I tried it this way
Server :
let filename = 'test_download.xlsx';
const buffer = fs.readFileSync(filename)
res.json(buffer);
Client :
file = await axios.get('/dataexplorer/test');
console.log(file);
console.log(XLSX.read(file.data, {type: "buffer"}));
First log :
Second log :
The problem is that it doesn't match my excel file at all just in terms of sheets (my file has 3 different sheet names)
Do you have any idea what the problem is?
Thanks
On the server-side just use:
const filename = 'test_download.xlsx';
// make sure to include the name and the extension of the file in the path
const filepath = 'your/path/to/the/file/test_download.xlsx';
/** filename is optional:
* if you don't pass it, the name of the file in the filepath will be used
* if you pass it the file at hte filepath will be downloaded with the name of `filename`
*/
res.download(filepath, filename);
This will return a blob to the client(make sure to include the correct headers for the response type) and then you can just save it or work with it with :
file = await axios.get('/dataexplorer/test',{ responseType: "blob"});
const ab = await file.data.arrayBuffer();
XLSX.read(Buffer.from(ab),{type:"buffer"})
I'm writing a Google Apps Script Web App, I'm facing a problem.
From server side I return the base64 encoded html code of a page:
function getRAW() {
var formText = 'https://www.google.com/';
var response = UrlFetchApp.fetch(formText);
var pdf1 = response.getAs('application/pdf');
//var myNewFile = DriveApp.createFile(pdf1);
var blob = response.getBlob()
var bytes = blob.getBytes();
var encoded = Utilities.base64Encode(bytes);
return encoded
}
And that works well.
Now, from client side, I want to download the base64 (is an html RAW content) as a pdf file (or .html if it is possible), but If I try to do like this I obtain a blank pdf page
function downloadRAW() {
var encoded = window.value;
var element = document.createElement('a');
element.setAttribute('href', 'data:application/pdf;base64,' + encoded);
element.setAttribute('download', 'prova');
element.style.display = 'none';
document.body.appendChild(element);
element.click();
document.body.removeChild(element);
}
Note that If I try to obtain a text/plain;base64, works perfectly (return a .txt) file; but this is not what I want.
How can I achieve it?
I believe your goal and your current situation as follows.
You want to convert the HTML data to a PDF data as the raw HTML code.
From I want to download the base64 (is an html RAW content) as a pdf file, I thought that the PDF data has the raw HTML code.
You want to make users download the HTML data as a PDF file.
var encoded = window.value; of your Javascript side is the value of encoded from the function of getRAW() of Google Apps Script.
Modification points:
In this case, in order to convert the raw HTML code (text data) to a PDF data, I would like to propose to use the Google Document. When Google Document is used, the text data can be converted to the PDF data.
When above points are reflected to your script, it becomes as follows.
Modified script:
In this case, please modify getRAW() at Google Apps Script side as follows.
function downloadRAW() {
var formText = 'https://www.google.com/';
var html = UrlFetchApp.fetch(formText).getContentText();
var doc = DocumentApp.create("temp");
doc.getBody().editAsText().setText(html);
doc.saveAndClose();
var file = DriveApp.getFileById(doc.getId());
var blob = file.getBlob();
var bytes = blob.getBytes();
var encoded = Utilities.base64Encode(bytes);
file.setTrashed(true);
return encoded
}
In this modification, at first, the retrieved HTML data is put to the Google Document created as a temporal document, and then, the Google Document is converted to the PDF data and converted to the base64 data, and return the data. And, the temporal Document is removed.
Note:
From (or .html if it is possible), if you want to export it as the text file, how about the following modification?
Google Apps Script side:
function downloadRAW() {
var formText = 'https://www.google.com/';
var blob = UrlFetchApp.fetch(formText).getBlob().setContentType("text/html");
var bytes = blob.getBytes();
var encoded = Utilities.base64Encode(bytes);
return encoded
}
Javascript side:
In this case, please modify element.setAttribute('href', 'data:application/pdf;base64,' + encoded); as follows.
element.setAttribute('href', 'data:text/html;base64,' + encoded);
From your question, I couldn't understand about the method for giving the value of encoded of Google Apps Script side to var encoded = window.value; of Javascript side. So if you want to see the sample script for this. I thought that this thread might be useful. Ref
When the blob of HTML is converted to application/json, the raw HTML code cannot be retrieved. The rendered result is obtained. Please be careful this.
References:
create(name) of Class DocumentApp
saveAndClose()
getFileById(id)
Even if the proposed solution by #Tanaike is very good, I do not want to use additional permission on writing file in the Google Drive of the user (since my script is executed as "Run as user"), so I decided to use JsPDF.
Client-side code:
<script src="https://cdnjs.cloudflare.com/ajax/libs/jspdf/1.3.2/jspdf.min.js"></script>
function downloadRAWPDF() {
// window.value is a global variable that contains base64 encoded content (passed from server)
var encoded = window.value;
var decoded = atob(encoded);
var doc = new jsPDF();
// Resize text to fit in an A4 page
var splitTitle = doc.splitTextToSize(decoded, 270);
var pageHeight = doc.internal.pageSize.height;
doc.setFontType("normal");
doc.setFontSize("11");
var y = 7;
for (var i = 0; i < splitTitle.length; i++) {
if (y > 280) {
y = 10;
doc.addPage();
}
doc.text(15, y, splitTitle[i]);
y = y + 7;
}
doc.save('myPDF.pdf');
}
Server-side code (Google Apps Script):
// #return RAW Response base64 encoded (without response headers)
function getRAW(formObject) {
// contains the value of an Input Field
var formText = formObject.myInput;
var response = UrlFetchApp.fetch(formText);
var blob = response.getBlob()
var bytes = blob.getBytes();
var encoded = Utilities.base64Encode(bytes);
return encoded
}
To convert the file in a html file the approach suggested by #Tanaike is perfect: data:text/html;base64, + encoded
Let me break down my requirement. Here's what I'm doing right now.
1. Generate PDF files from HTML
for this I'm using Weasyprint as following:
lstFileNames = []
for i, content in enumerate(lstHtmlContent):
repName = 'report'+ str(uuid.uuid4()) + '.pdf'
lstFileNames.append("D:/Python/Workspace/" + repName)
HTML(string=content).write_pdf(target=repName,
stylesheets=[CSS(filename='/css/bootstrap.css')])
all files names, with paths, are saved in lstFileNames.
2. Create a zip file with pdf files generated by weasyprint
for this I'm using zipfile
zipPath = 'reportDir' + str(uuid.uuid4()) + '.zip'
myzip = zipfile.ZipFile(zipPath, 'w')
with myzip:
for f in lstFileNames:
myzip.write(f)
3. Send zip file to client for download
resp = HttpResponse(myzip, content_type = "application/x-zip-compressed")
resp['Content-Disposition'] = 'attachment; filename=%s' % 'myzip.zip'
4. Open file for downloading via Javascript
var file = new Blob([response], {type: 'application/x-zip-compressed'});
var fileURL = URL.createObjectURL(file);
window.open(fileURL);
Problems
1. While the zip file is successfully received at front end, after I try to open it, it gives the following error:
The archive is in either unknown format or damaged
Am I sending the file wrong or is my Javascript code the problem?
2. Is there a way to store all pdf files in list of byte arrays and generate zip files with those byte array and send it to the client? I tried that with weasyprint but the result was same damaged file.
3. Not exactly a problem but I haven't been able to find it in weasyprint docs. Can I enforce the path to where the file should be saved?
Problem # 1 is of extreme priority, rest are secondary. I would like to know if I'm doing it right i.e. generating pdf files and sending their zip file to client.
Thanks in advance.
A slightly different approach would be to move the zip file to a public directory and then send that location to the client (e.g. json formatted), i.e.:
publicPath = os.path.join('public/', os.path.basename(zipPath))
os.rename(zipPath, os.path.join('/var/www/', publicPath))
jsonResp = '{ "zip-location": "' + publicPath + '" }'
resp = HttpResponse(jsonResp, content_type = 'application/json');
Then in your client's javascript:
var res = JSON.parse(response);
var zipFileUrl = '/' + res['zip-location'];
window.open(zipFileUrl, '_blank');
'/' + res['zip-location'] assumes that your page lives in the same folder as the public directory (so http://example.com/public/pdf-files-123.zip points to /var/www/public/pdf-files-123.zip on your file system).
You can clean up the public directory with a cron job that deletes all the .zip files in there that are older than an hour or so.
Once you have exited the with block the filehandle is closed. You should reopen the file (this time with open) and use read() to pass the contents to HttpResponse instead of passing the filehandle itself.
with zipfile.ZipFile(zipPath, 'w') as myzip
for f in lstFileNames:
myzip.write(f)
with open(zipPath, 'r') as myzip:
return HttpResponse(myzip.read(), content_type = "application/x-zip-compressed")
If that works, then you can use a StringIO instance instead of a filehandle to store the zip file. I'm not familiar with Weasyprint so I don't know whether you can use StringIO for that.
I'm trying to write a Json object (JsonExport) and I'd like to write its content into a text file.
I'm using max4live to export data from Audio DAW to Json in order to export to a server, but after that I would like to see the whole Json Object in a text file:
var txtFile = "test.txt";
var file = new File(txtFile);
var str = JSON.stringify(JsonExport);
file.open("write"); // open file with write access
file.write(str);
file.close();
The compiler runs with no error, but i can not get the text file. I have used as well path to some of my directories and nothing.
Any idea what's happening? Thanks
I know this question already has accepted answer but I think my answer could help someone. So, the problem is to export Json data to a text file. Once you execute the following code, file will be downloaded by the browser.
const filename = 'data.json';
const jsonStr = JSON.stringify(JsonExport);
let element = document.createElement('a');
element.setAttribute('href', 'data:text/plain;charset=utf-8,' + encodeURIComponent(jsonStr));
element.setAttribute('download', filename);
element.style.display = 'none';
document.body.appendChild(element);
element.click();
document.body.removeChild(element);
If you have access to an already existing file, just link to it. You can specify what the downloaded file name will be like this:
<a href="path/to/file.txt" download="example.json">
Download as JSON
</a>
If needed, you could also write out the dataURI as well
//Get the file contents
var txtFile = "test.txt";
var file = new File(txtFile);
var str = JSON.stringify(JsonExport);
//Save the file contents as a DataURI
var dataUri = 'data:application/json;charset=utf-8,'+ encodeURIComponent(str);
//Write it as the href for the link
var link = document.getElementById('link').href = dataUri;
Then just give the link an ID and a default href
<a href="#" id="link" download="example.json">
Download as JSON
</a>
Finally I got it! It worked by changing few parameters like this:
var txtFile = "/tmp/test.txt";
var file = new File(txtFile,"write");
var str = JSON.stringify(JsonExport);
log("opening file...");
file.open();
log("writing file..");
file.writeline(str);
file.close();
Path to my directories not allowed, so i had to save it on /tmp directory.
Thanks to all!
Is there a way to treat a local file (on the server) as if it was uploaded? Like fetch the file contents and put it in a array like it was a uploaded file?
So I could use it like
var file = someFunctionToRetrieveFile( url );
var re = /(?:\.([^.]+))?$/;
var name = file.name;
var ext = re.exec( name )[0];
var type = file.type;
? Is this possible in JavaScript?