I want to embed a javascript snippet inside of a pdf file so that it will immediately print when it's opened from a browser window. To try and achieve this I'm following this example here.
I have created a helper class that has a static method to handle this task. I already have the pdf file path string ready to pass into the method. What I don't understand is how the output stream portion of this works. I would like the updated pdf to be saved to my servers hard drive. I do not want to stream it back to my browser. Any guidance would be greatly appreciated.
public class PdfHelper
{
public static void AddPrintFunction(string pdfPath, Stream outputStream)
{
PdfReader reader = new PdfReader(pdfPath);
int pageCount = reader.NumberOfPages;
Rectangle pageSize = reader.GetPageSize(1);
// Set up Writer
PdfDocument document = new PdfDocument();
PdfWriter writer = PdfWriter.GetInstance(document, outputStream);
document.Open();
//Copy each page
PdfContentByte content = writer.DirectContent;
for (int i = 0; i < pageCount; i++)
{
document.NewPage();
// page numbers are one based
PdfImportedPage page = writer.GetImportedPage(reader, i + 1);
// x and y correspond to position on the page
content.AddTemplate(page, 0, 0);
}
// Inert Javascript to print the document after a fraction of a second to allow time to become visible.
string jsText = "var res = app.setTimeOut(‘var pp = this.getPrintParams();pp.interactive = pp.constants.interactionLevel.full;this.print(pp);’, 200);";
//string jsTextNoWait = “var pp = this.getPrintParams();pp.interactive = pp.constants.interactionLevel.full;this.print(pp);”;
PdfAction js = PdfAction.JavaScript(jsText, writer);
writer.AddJavaScript(js);
document.Close();
}
}
For how to accomplish this task, please take a look at this and this SO posts.
Basically you should have something like this:
var pdfLocalFilePath = Server.MapPath("~/sourceFile.pdf");
var outputLocalFilePath = Server.MapPath("~/outputFile.pdf");
using (var outputStream = new FileStream(outputLocalFilePath, FileMode.CreateNew))
{
AddPrintFunction(pdfLocalFilePath, outputStream);
outputStream.Flush();
}
Related
I had to place videos(mp4-files) in one photoshop document. I thought it would be easier to find a solution with png/jpg, and then project it on mp4. but the fact is that photoshop saving png/jpg and mp4 in different ways. Therefore, despite the fact that there is an import solution, I have difficulties with exporting mp4 by code.
I have 2 arrays of mp4 files and each mp4 from the first array needs to be overlaid on each of the second and saved by mp4. I solved the problem by uploading a video to an open photoshop file with a simple code:
function replaceContents(newFile) {
var docRef = app.open(newFile);
return docRef;
}
function importVideos(order_number) {
var doc = app.activeDocument;
var file = new File('E:/path/' + order_number + '.mp4');
// open a new document with needed video
var docTemp = replaceContents(file);
// copy opend layer with video from new doc to my main doc
var layer = docTemp.activeLayer.duplicate(doc.layerSets.getByName(color), ElementPlacement.PLACEATEND);
// close new unnecessary doc
docTemp.close(SaveOptions.DONOTSAVECHANGES);
layer.name = order_number;
return layer;
}
Here is the code for saving videos and in doExport() doc should be saved as a video.
function Saving(color) {
var array1 = app.activeDocument.layerSets.getByName('s');
var array2 = app.activeDocument.layerSets.getByName(color);
for (i = 0; i < 5; i++) {
array1.artLayers[i].visible = true;
for (j = 0; j < 5; j++) {
array2.artLayers[i].visible = true;
doExport();
array2.artLayers[i].visible = false;
}
array1.artLayers[i].visible = false;
}
}
So a new question: how to export a video from photoshop with a code with the ability to specify the file name and the save path?
P.S. if you do this through Actions, you can't enter input parameters like the name of the saved file, it seals the Action as you did it.
If you know how to create arguments for Actions, you are welcome!
The Goal: I am currently taking a file from javascript, converting it into a base64 encoded string of a byte array and passing it to my .net controller.
I am then processing that by converting that back into a byte array, creating a new memory stream of it, creating an Image object from the memory stream, changing what I need to change about it, and then bringing it back into a memory stream to then upload to my server.
The problem:
I currently am able to take an image in from JavaScript encoded like I had mentioned earlier, and upload it to the server no problem, however the issue comes in when I am trying to convert my memory stream to an Image (so that I can resize it). I am not sure why, but on my local machine it has no problems and doesn't throw any errors and uploads perfectly fine, resized and everything. However on my linux server, it gets to the log line right before it try's to create the image from the memory stream, it doesn't actually throw an exception, but just stops working and returns to my controller.
I am not really sure what is going on but hopefully some of you fine people can help :).
The code:
public async Task<DataOpResult<string>> UploadFile(StorageUploadFile file, string FileGuid)
{
Console.WriteLine("Start Upload");
DataOpResult<string> uploadFile = new DataOpResult<string>();
uploadFile.Status = DataOpResultStatus.Success;
try
{
//create storage client
StorageClient storage = await StorageClient.CreateAsync(credential);
Console.WriteLine("Created storage");
//convert file data and create Image Object
byte[] dataArray = Convert.FromBase64String(file.FileData);
Console.WriteLine("Got byte array");
Image imageVar = CreateImage(dataArray);
Console.WriteLine("Converted image");
//convert with aspect ratio
var aspectRatio = (decimal)(imageVar.Width) / (decimal)(imageVar.Height);
var newHeight = 150;
int newWidth = (int)(newHeight * aspectRatio);
//Resize Image
Console.WriteLine("Resize image");
Image resizedImage = ResizeImage(imageVar, newWidth, newHeight);
MemoryStream resizedStream = new MemoryStream();
resizedImage.Save(resizedStream, imageVar.RawFormat);
Console.WriteLine("got new memory stream");
// IUploadProgress defined in Google.Apis.Upload namespace
var progress = new Progress<IUploadProgress>(
p => Console.WriteLine($"bytes: {p.BytesSent}, status: {p.Status}")
);
// var acl = PredefinedAcl.PublicRead // public
var acl = PredefinedObjectAcl.AuthenticatedRead; // private
var options = new UploadObjectOptions { PredefinedAcl = acl };
Console.WriteLine("Upload Images");
var result = await storage.UploadObjectAsync("echochat-292801.appspot.com", $"{FileGuid}/{file.FileName}", file.FileType, resizedStream, options, progress: progress);
Console.WriteLine(result.ToString());
uploadFile.DataItem = result.MediaLink;
} catch (Exception ex)
{
uploadFile.Status = DataOpResultStatus.Error;
uploadFile.ThrownException = ex;
}
return uploadFile;
}
public static Image CreateImage(byte[] imageData)
{
Image image;
using (MemoryStream inStream = new MemoryStream())
{
inStream.Write(imageData, 0, imageData.Length);
image = Image.FromStream(inStream);
}
return image;
}
Running sudo apt-get install libgdiplus
on the my server ended up working!
I have a aurelia client that gets a image from my asp.net server via my API. The image is served from the server that holds a Emgu CV UMat var. With the following method in my controller i get the image and it is displayed correctly.
This method results in memory leakage and i can't seem to get to the orgin (not calling the method, means no leak):
Update, i tried Mawg's suggestion but when i close the stream it will not show the image. The leak is gone then but there is no image.
[System.Web.Http.HttpGet]
[System.Web.Http.Route("dummymethod3")]
public HttpResponseMessage Get2()
{
HttpResponseMessage response = new HttpResponseMessage();
try
{
Console.WriteLine("Get image 3");
ddEngine.sem.WaitOne();
var memoryStream = new MemoryStream();
ResultImage.Bitmap.Save(memoryStream, ImageFormat.Png);
memoryStream.Position = 0;
var result = new HttpResponseMessage(HttpStatusCode.OK);
result.Content = new StreamContent(memoryStream);
result.Content.Headers.ContentType = new MediaTypeHeaderValue("image/png");
memoryStream.Close();
memoryStream.Dispose();
ddEngine.sem.Release();
return result;
}
catch
{
Console.WriteLine("Ex");
}
return response;
}
I have tried to call the collector at several places in the code like:
GC.Collect();
GC.WaitForPendingFinalizers();
When doing this it releases resources but the memory usege is slowly increasing. When not calling the get method there is no increase!
My client code looks like this:
updateImageSrc() {
let dt = new Date();
let baseUrl = "http://localhost:8080/api/status/dummymethod3";
this.imagePath = baseUrl + "?t=" + dt.getTime();
}
And the html
<img id="img" src.bind="imagePath"/>
Any suggestions are welcome!
I need to download the selected files in a grid on download button click. I am using knokout.js and web api
Using the below given response I was able to download a single file
self.DownloadDoc = function () {
window.location.assign("http://localhost:8092/api/Document/GetResponse?id=" + self.selectedDocuments()[0]);
self.selectedDocuments.removeAll();
self.bindDocuments();
};
I tried looping this window.location.assign() code using for loop,but as it is synchronous call,its downloading only one file.
Html part
<span>Download</span><small></small>
Web Api code
[HttpGet]
public HttpResponseMessage GetResponse(string id)
{
HttpResponseMessage response = Request.CreateResponse(HttpStatusCode.OK);
List<DocumentsModel> documents = _service.GetDocumentContent(Convert.ToInt32(id));
byte[] fileBytes = documents.FirstOrDefault().FileContent;
System.Net.Http.Headers.MediaTypeHeaderValue mediaType = new System.Net.Http.Headers.MediaTypeHeaderValue("application/octet-stream");
if (fileBytes != null)
response.Content = new ByteArrayContent(fileBytes);
response.Content.Headers.ContentType = mediaType;
response.Content.Headers.ContentDisposition = new System.Net.Http.Headers.ContentDispositionHeaderValue("attachment");
response.Content.Headers.ContentDisposition.FileName = documents.FirstOrDefault().FileLeafRef;
return response;
}
this part self.selectedDocuments()[0], looks like it will force download always only of first document.
Not sure what is your structure and output of selectedDocuments(),
for example, if it outputs array, with fileID nodes, maybe you should try with this:
<div data-bind="foreach: self.selectedDocuments()">
<span>Download</span><small></small>
</div>
then, you will have to pass param in function:
self.DownloadDoc = function (fileID) {
window.location.assign("http://localhost:8092/api/Document/GetResponse?id=" + fileID);
self.selectedDocuments.removeAll();
self.bindDocuments();
};
When a video on my local storage—let's say it's currently located at file:///home/user/video.m4v—is opened by dragging it into a new tab in Chrome, how can I calculate the SHA-1 checksum for the file using JavaScript?
Purpose:
I am planning to write a Chrome extension which will store the calculated checksum of videos (files with extensions matching a pattern) as localStorage objects in order to save the playback position of video upon tab close and then restore it when the file is loaded again, even if the location or filename of the video is changed.
You need a crypto library for this. A well known one is Google CryptoJS.
I found this as an specific example for your task: https://gist.github.com/npcode/11282867
After including the crypto-js source:
function sha1sum() {
var oFile = document.getElementById('uploadFile').files[0];
var sha1 = CryptoJS.algo.SHA1.create();
var read = 0;
var unit = 1024 * 1024;
var blob;
var reader = new FileReader();
reader.readAsArrayBuffer(oFile.slice(read, read + unit));
reader.onload = function(e) {
var bytes = CryptoJS.lib.WordArray.create(e.target.result);
sha1.update(bytes);
read += unit;
if (read < oFile.size) {
blob = oFile.slice(read, read + unit);
reader.readAsArrayBuffer(blob);
} else {
var hash = sha1.finalize();
console.log(hash.toString(CryptoJS.enc.Hex)); // print the result
}
}
}
I wouldn't recommend to calculate a hash over the whole video file as it can be pretty resource consuming depending on the file size. Maybe you can use just the meta information or reconsider about the filename and filepath again?
Web APIs have progressed considerably since I asked this question. Calculating a hex digest is now possible using the built-in SubtleCrypto.digest().
TS Playground link
function u8ToHex (u8: number): string {
return u8.toString(16).padStart(2, '0');
}
/** Ref: https://developer.mozilla.org/en-US/docs/Web/API/SubtleCrypto/digest#supported_algorithms */
const supportedAlgorithms = [
'SHA-1',
'SHA-256',
'SHA-384',
'SHA-512',
] as const;
type SupportedAlgorithm = typeof supportedAlgorithms[number];
type Message = string | Blob | BufferSource;
async function hexDigest (
algorithm: SupportedAlgorithm,
message: Message,
): Promise<string> {
let buf: BufferSource;
if (typeof message === 'string') buf = new TextEncoder().encode(message);
else if (message instanceof Blob) buf = await message.arrayBuffer();
else buf = message;
const hash = await crypto.subtle.digest(algorithm, buf);
return [...new Uint8Array(hash)].map(u8ToHex).join('');
}