I'm working on Office Add-in project, I need to get current Office file and upload to our server.
Below is upload file from File Browser to our server
var fdata = new FormData();
fdata.append('data', file);
fdata.append('totalFileSizeBytes', file.size);
fdata.boundary = '----boundary';
xhr.send(fdata);
And I got Office file info via function: Document.getFileAsync (https://dev.office.com/reference/add-ins/shared/document.getfileasync)
But I don't know how to convert File info from Document.getFileAsync to FormData.
I tried read File info slice by slice then concat to an array and pass to FormData, but it wasn't success.
The answer is a bit late, but hopefully might help future folks looking for this - I wasted some time trying to figure this out.
The File object returned by the Document.getFileAsync is not usable with FormData. Also what the Microsoft Documentation shows you does not get you a file that you can just drop into FormData.
First, you'll have to combine the slices returned to a docdata array as per the Microsoft example shows (https://learn.microsoft.com/en-us/javascript/api/office/office.document?view=office-js#getfileasync-filetype--options--callback-). But then instead of creating a string out of it by using charCodeAt, you'll want just use the combined docdata array and do this:
const file = new File(
[new Uint8Array(docdata)],
'testfile.docx',
{ type: 'application/vnd.openxmlformats-officedocument.wordprocessingml.document' }
);
Which you can then proceed to append to your FormData:
const fd = new FormData();
fd.append('file', file);
The new File() gave me an error. But the a new Blob() did the trick
var aFile = new Blob(
[new Uint8Array(docdata)],
{ type: 'application/vnd.openxmlformats-officedocument.wordprocessingml.document' }
);
formData.append('file', aFile, 'testfile.docx');
Related
I'm trying to save some data from API in a .json file using cy.writeFile method, but my code is replacing the existing data.
What I need is to add additional data.
cy.intercept('POST', 'http://viasphere.localhost/sites/datatable').as('response')
cy.contains('Sortir').click()
cy.wait('#response').get('#response').then(xhr => {
console.log(xhr)
let siteID = xhr.response.body.data[0].id
let creationDate = xhr.response.body.data[0].created_at
let RM = xhr.response.body.data[0].metal_rollout
let clientGroup = xhr.response.body.data[0].client_contact_group
cy.writeFile('SiteAPIdata.json', {siteID2: siteID})
After the run, the data existing inside the SiteAPIdata.json file is being replaced by the new data.
The SiteAPIdata.json file is located in cypress/fixtures/ folder.
Thank you!
Assuming you want to append the new data to the existing data, that can easily be accomplished by using cy.readFile() before writing.
...
cy.readFile('SiteAPIdata.json').then((data) => {
data.siteID = siteID;
cy.writeFile('SiteAPIdata.json', data);
})
I am able to successfully attach PDF file with ServiceNow table record using GlideSysAttachment API and attachment.write() function in script, however whenever I download and try to open same, I get the error shown in below screenshot.
Code snippet
(function execute() {
try{
var rec = new GlideRecord('incident');
var attachment = new GlideSysAttachment();
var incidentSysID = incident.number;
rec.get(incidentSysID);
var fileName = 'Test_Incident.pdf';
var contentType = 'application/pdf'; // Also tried with contentType as 'text/pdf'
var content = pdf_content;
var agr = attachment.write(rec, fileName, contentType, content);<br>
gs.info('The PDF attachment sys_id is: ' + agr);
}catch(err){
gs.log('Got Error: ' + err);
gs.info(err);
}
})()
I also tried "AttachmentCreator" with ecc_queue within script but same error occurs. Below is code for it.
(function execute()
{var attCreator = new GlideRecord('ecc_queue');
attCreator.agent = "AttachmentCreator";
attCreator.topic = "AttachmentCreator";
attCreator.name = "Test.pdf" + ":" + "text/pdf";
//Also tried, "Test.pdf:application/pdf"
attCreator.source = "incident"+":"+ incident.number;
// Record Table name and sys_id of the particular record
var content = pdf_content; // pdf_content is any string variable
var stringUtil = new GlideStringUtil();
var base64String = stringUtil.base64Encode(content);
var isValid=GlideStringUtil.isBase64(base64String);
var base64String= gs.base64Encode(content);
gs.info("Is valid base64 format in ecc_queue ? "+ isValid);
attCreator.payload = base64String; //base64 content of the file
attCreator.insert();
})()
I am able to attach and view excel and word files with similar scripts without any issues. I have checked system properties for attachments but everything looks fine. I am able to view the PDF file uploaded from UI to particular table records however not the one I attach via REST API or scripts.
I have also tried sending encoded data as bytes, base64 or simple string but nothing seems to work. I don't get any errors and attachment id is returned each time on creation of attachment.
After modifying my code slightly for above functions w.r.t scoped application instead of global; I got some information from logs when I debug:
05:38:38.411 Security restricted: File type is not allowed or does not match the content for file Test.pdf
05:38:38.410 Security restricted: MIME type mismatch for file: Test.pdf. Expected type:application/pdf, Actual type: text/plain
05:38:38.394 App:XYZ App x_272539_xyz_ap: Is valid base64 format in ecc_queue ? true
First a comment: This line in your code is accidentally working -- make sure you understand that a task number is not the object sys_id
var incidentSysID = incident.number; // should be incident.sys_id
Next, it's unclear where the PDF content is coming from. IF your complete code is listed, I would expect the errors given as you have noted that pdf_content is "any string variable."
ServiceNow does have a the capability to create a PDF from an HTML argument.
Generating a PDF from HTML
Here's a helpful blog post for getting a PDF (Platform generated) of an existing record:
Love PDF? PDF loves you too
I am trying to download a 1GB file from blob storage into the client. I used before Memory Stream and I get OutOfMemory exception.
now I am trying to open a read stream from the blob and send it directly to the client.
[HttpGet]
[ResponseType(typeof(HttpResponseMessage))]
public async Task<HttpResponseMessage> DownloadAsync(string file)
{
HttpResponseMessage result = new HttpResponseMessage(HttpStatusCode.OK);
var stream = await blob.OpenReadAsync("container", file);
result.Content = new StreamContent(stream);
return result;
}
The file is downloaded correctly, but the problem is: The code download the complete stream in the client, then the client sees the downloaded file.
I wanted the client to see the file as being downloaded, so the user knows that he is downloading something. Not just blocking the request and wait till it finished.
I am using FileSaver in Angular2:
this.controller.download('data.zip').subscribe(
data => {
FileSaver.saveAs(data, 'data.zip');
});
Has anybody an idea how to fix it?
Thank you!
To fix it you'd need to use the following javascript code instead:
var fileUri = "http://localhost:56676/api/blobfile"; //replace with your web api endpoint
var link = document.createElement('a');
document.body.appendChild(link);
link.href = fileUri;
link.click();
And then in your backend, make it like so:
HttpResponseMessage result = new HttpResponseMessage(HttpStatusCode.OK);
var stream = await blob.OpenReadAsync("container", file);
result.Content = new StreamContent(stream);
result.Content.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment")
{
FileName = "data.zip"
};
result.Content.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream");
return result;
I had the same problem.
The Solution I sorted out was -
First thing, the expected behaviour can occur only when client tries to download the file from blob and usually I prefer downloading the file from the client itself.
As in your case, try to get file blob uri and do some operations as below to open file in browser using Angular Router or simply window.location.href.
window.location.href = “https://*/filename.xlsx”
This worked for me.
My requirement is to use Web API to send across the network, a zip file (consisting a bunch of files in turn) which should not be written anywhere locally (not written anywhere on the server/client disk). For zipping, I am using DotNetZip - Ionic.Zip.dll
Code at Server:
public async Task<IHttpActionResult> GenerateZip(Dictionary<string, StringBuilder> fileList)
{
// fileList is actually a dictionary of “FileName”,”FileContent”
byte[] data;
using (ZipFile zip = new ZipFile())
{
foreach (var item in filelist.ToArray())
{
zip.AddEntry(item.Key, item.Value.ToString());
}
using (MemoryStream ms = new MemoryStream())
{
zip.Save(ms);
data = ms.ToArray();
}
}
var result = new HttpResponseMessage(HttpStatusCode.OK);
MemoryStream streams = new MemoryStream(data);
//, 0, data.Length-1, true, false);
streams.Position = 0;
//Encoding UTFEncode = new UTF8Encoding();
//string res = UTFEncode.GetString(data);
//result.Content = new StringContent(res, Encoding.UTF8, "application/zip");
<result.Content = new StreamContent(streams);
result.Content.Headers.ContentType = new MediaTypeHeaderValue("application/zip");
//result.Content.Headers.ContentLength = data.Length;
result.Content.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment");
result.Content.Headers.ContentDisposition.FileName = "test.zip";
return this.Ok(result);
}
The issue I am facing is that after the zip file downloaded at client end when modified as a test.bin has its stream contents (byte[] data in this example’s contents) missing. (I am getting back a test.zip file. When I change the file locally from test.zip to test.bin, I am seeing that the File’s contents as shown below. It does not contain the Response.Content values. P.S. I have also tried the MIME type “application/octet-stream” as well. No luck!)
Test.zip aka test.bin’s contents:
{"version":{"major":1,"minor":1,"build":-1,"revision":-1,"majorRevision":-1,"minorRevision":-1},
"content":{"headers":[{"key":"Content-Type","value":["application/zip"]},
{"key":"Content-Disposition","value":["attachment; filename=test.zip"]}]},
"statusCode":200,"reasonPhrase":"OK","headers":[],"isSuccessStatusCode":true}
Can someone please help me on how we can set result.Content with a MemoryStream object (I have seen example of “FileStream” at other places on google to set “result.Content” but I want to use MemoryStream object only!). I am highlighting this because I think the problem lies with setting the MemoryStream object to the result.Content (in order to properly save the streams content into the result.Content object)
P.S. I have also gone thru Uploading/Downloading Byte Arrays with AngularJS and ASP.NET Web API (and a bunch of other links) but it did not help me much… :(
Any help is greatly appreciated. Thanks a lot in advance :)
I got my issue solved!!
All I did was to change the Response Type to HttpResponseMessage and use "return result" in the last line rather than Ok(result) { i.e. HttpResponseMessage Type rather than OKNegiotatedContentResult Type)
and thanks in advance for any help you guys can give me. I am trying to use mongodb, mongoose, gridfs-strea, and express to store img files on mongodb.
I do not want to store the file in a folder. I want gfs.createWriteStream to take the file directly from app.post from express. App.post is currently saving some strings through a schema model into mongodb.
The form that routes to app.post contains strings and a input for img file.
I tried to do this(dnimgfront being the name of the input):
dnimgfront:req.pipe(gfs.createWriteStream('req.body.dnimgfront'))
I am getting back.
TypeError: Object function Grid(db, mongo) {
if (!(this instanceof Grid)) {
return new Grid(db, mongo);
}
mongo || (mongo = Grid.mongo ? Grid.mongo : undefined);
My problem is I have to be able to store the img and the strings from the same app.post save function. Any ideas?
What I'm using to connect to mongodb is:
mongoose.connect('mongodb://localhost/veeltaxi');
var con=mongoose.connection;
con.once('open', function(){
console.log('connected to mongodb succesfully!')
});
Thanks in advance for your help.
First, you need an instead of gridfs-stream:
var GridStream = require('gridfs-stream');
var mongodb = require('mongodb');
var gfs = new GridStream(mongoose.connection,mongodb);
At which point you can create the write stream and pipe:
var writeStream = gfs.createWriteStream({
filename: filename, // the name of the file
content_type: mimetype, // somehow get mimetype from request,
mode: 'w' // ovewrite
});
req.pipe(writeStream);
However, at this time the Node.js MongoDB Driver is at version 2.0 which uses Streams 2, so there is no reason to use gridfs-stream if you're using that version of the mongodb lib. See the source code for v2.0.13. FYI, the stream that is implemented in the updated driver is Duplex. (Aside: gridfs-stream has its share of problems, and while actively maintained, is not very frequent.)