Problem with Firebase Image Resize extension [duplicate] - google-cloud-functions

I am following a tutorial to resize images via Cloud Functions on upload and am experiencing two major issues which I can't figure out:
1) If a PNG is uploaded, it generates the correctly sized thumbnails, but the preview of them won't load in Firestorage (Loading spinner shows indefinitely). It only shows the image after I click on "Generate new access token" (none of the generated thumbnails have an access token initially).
2) If a JPEG or any other format is uploaded, the MIME type shows as "application/octet-stream". I'm not sure how to extract the extension correctly to put into the filename of the newly generated thumbnails?
export const generateThumbs = functions.storage
.object()
.onFinalize(async object => {
const bucket = gcs.bucket(object.bucket);
const filePath = object.name;
const fileName = filePath.split('/').pop();
const bucketDir = dirname(filePath);
const workingDir = join(tmpdir(), 'thumbs');
const tmpFilePath = join(workingDir, 'source.png');
if (fileName.includes('thumb#') || !object.contentType.includes('image')) {
console.log('exiting function');
return false;
}
// 1. Ensure thumbnail dir exists
await fs.ensureDir(workingDir);
// 2. Download Source File
await bucket.file(filePath).download({
destination: tmpFilePath
});
// 3. Resize the images and define an array of upload promises
const sizes = [64, 128, 256];
const uploadPromises = sizes.map(async size => {
const thumbName = `thumb#${size}_${fileName}`;
const thumbPath = join(workingDir, thumbName);
// Resize source image
await sharp(tmpFilePath)
.resize(size, size)
.toFile(thumbPath);
// Upload to GCS
return bucket.upload(thumbPath, {
destination: join(bucketDir, thumbName)
});
});
// 4. Run the upload operations
await Promise.all(uploadPromises);
// 5. Cleanup remove the tmp/thumbs from the filesystem
return fs.remove(workingDir);
});
Would greatly appreciate any feedback!

I just had the same problem, for unknown reason Firebase's Resize Images on purposely remove the download token from the resized image
to disable deleting Download Access Tokens
goto https://console.cloud.google.com
select Cloud Functions from the left
select ext-storage-resize-images-generateResizedImage
Click EDIT
from Inline Editor goto file FUNCTIONS/LIB/INDEX.JS
Add // before this line (delete metadata.metadata.firebaseStorageDownloadTokens;)
Comment the same line from this file too FUNCTIONS/SRC/INDEX.TS
Press DEPLOY and wait until it finish
note: both original and resized will have the same Token.

I just started using the extension myself. I noticed that I can't access the image preview from the firebase console until I click on "create access token"
I guess that you have to create this token programatically before the image is available.
I hope it helps

November 2020
In connection to #Somebody answer, I can't seem to find ext-storage-resize-images-generateResizedImage in GCP Cloud Functions
The better way to do it, is to reuse the original file's firebaseStorageDownloadTokens
this is how I did mine
functions
.storage
.object()
.onFinalize((object) => {
// some image optimization code here
// get the original file access token
const downloadtoken = object.metadata?.firebaseStorageDownloadTokens;
return bucket.upload(tempLocalFile, {
destination: file,
metadata: {
metadata: {
optimized: true, // other custom flags
firebaseStorageDownloadTokens: downloadtoken, // access token
}
});
});

Related

Firebase Cloud Functions-ImageMagick CLI PDF to images

I am trying to work with Firebase Cloud Functions, and ImageMagick, similar to how the thumbnail demo is done. By re-purposing the demo script, I want to execute a CLI command for ImageMagick to split PDF pages to images.
convert -density 150 presentation.pdf -quality 90 output-%3d.jpg
The snippet
exports.splitPdfPages = functions.storage.object().onFinalize(async (object) => {
const fileBucket = object.bucket; // The Storage bucket that contains the file.
const filePath = object.name; // File path in the bucket.
const contentType = object.contentType; // File content type.
const metageneration = object.metageneration; // Number of times metadata has been generated. New objects have a value of 1.
// Download file from bucket.
const bucket = admin.storage().bucket(fileBucket);
const tempFilePath = path.join(os.tmpdir(), fileName);
const tempSplitImagesPath = tempFilePath.replace(".png", "_%3d.png");
await bucket.file(filePath).download({destination: tempFilePath});
console.log('PDF downloaded locally to', tempFilePath);
// Generate split page images using ImageMagick.
await spawn('convert', ['-density', '150', tempFilePath, '-quality', '90', tempSplitImagesPath]);
console.log('pages split images created at', tempFilePath);
...
// Uploading the split images.
...
// Once the thumbnail has been uploaded delete the local file to free up disk space.
return fs.unlinkSync(tempFilePath);
});
Unfortunately, I'm encountering errors in the Cloud Functions log indicating the statement error
ChildProcessError: convert -density 150 /tmp/7eCxdDKqCb0rlYVw3AYf__foobar.pdf -quality 100 /tmp/7eCxdDKqCb0rlYVw3AYf__foobar_%3d.png failed with code 1
I searched for resolution to the error, but it only indicates that whitespaces are the main reason for the issue (which based on my statement doesn't have any). Invoking generateThumbnail function works properly, so I'm presuming its based on my changes
Am I missing something to properly call the ImageMagick command for converting PDF pages to image?
Looking forwad to hearing from you.

How to open on a specific page a PDF File on Forge Viewer?

I need to open a PDF file from BIM 360 Docs on the Viewer selecting a specific page. I'm currently opening the PDF on the Viewer but I don't know how to select a page.
Adding on to my comment, you can get a list of all available viewables when using the onDocumentLoadSucces callback. This callback is triggered after initting the viewer and loading the first Urn(model) into the viewer. You can look into more functionality on bubble nodes in the documentation
Example in angular/typescript:
private onDocumentLoadSucces(viewerDocument: Autodesk.Viewing.Document) {
// Default viewable
let defaultModel = viewerDocument.getRoot().getDefaultGeometry();
// list of all viewables in this model
this.viewables = viewerDocument.getRoot().search({'type':'geometry'});
// We load in the default viewable here but we could choose to load any viewable
// in this.viewables
this.viewer.loadDocumentNode(viewerDocument, defaultModel);
console.log('model changed');
}
I assume you are using the PDF extension to directly load and view PDF. If so, you can tell it the page number in the loadModel call. For example:
viewer.loadModel( pdf, {page:2});
Here's the whole function:
function initializeViewer( pdf ) {
var options = {
env: "Local",
useADP: false
}
Autodesk.Viewing.Initializer(options, () => {
viewer = new Autodesk.Viewing.Private.GuiViewer3D(document.getElementById('viewer3D'));
viewer.setTheme("light-theme");
viewer.start();
if (!pdf) return;
viewer.loadExtension('Autodesk.PDF').then( () => {
viewer.loadModel( pdf, {page:2});
});
});
};
The docs mention this here:
https://forge.autodesk.com/en/docs/viewer/v7/reference/Extensions/PDFExtension/
and there is also an example I used to test from a blog post here:
https://forge.autodesk.com/blog/fast-pdf-viewingmarkup-inside-forge-viewer
hope it helps

How can upload a image from system to angular project without browsing the image instead of clicking one button?

My aim is to upload a image from local system (means a specified folder) into my angular project ,Without browsing and using a button function i need to get the image into my project,,So when the card reader reads the card automatically a folder would generate in c , i wanna take image from there
anyone know about it?
Try to insert this piece of code from here you can upload files from your local system.
selectAFile: File = null;
onFileSelection(event) {
this.selectAFile = <File>event.target.files[0]
}
now upload function and select a storage place
upload() {
const fd = new FormData();
fd.append('image', this.selectAFile, this.selectAFile.name);
this.http.post('storageplacelink', fd).subscribe(res => {
console.log(res)
})
}

How would you create a downloadable pdf in a client side app?

One of our requirements for an admin tool is to create a form that can be filled and translated to a downloadable pdf file. (A terms and condition with blank input fields to be exact).
I did some googling and tried creating a form in html and css and converted it into a canvas using the html2canvas package. Then I used the jspdf package to convert it into a pdf file. The problem is that I cannot get it to fit and resize accordingly to an a4 format with correct margins. I'm sure I can get to a somewhat working solution if I spend some time on it.
However, my real question is how would you guys solution this? Is there a 3rd party app/service that does this exact thing? Or would you do all this in the server side? Our current app is using angular 7 with firebase as our backend.
Cheers!
I was able to use the npm package pdfmake to create a dynamic pdf based on user information the user provided while interacting with my form. (I was using React) It opened the pdf in a new tab and the user is able to save the pdf. In another application (still React),
I used the same package to create a receipt so you can customize the size of the "page". We created the pdf and used the getBase64() method and sent the pdf as an email attachement.
My service function:
getEvidenceFile(id: number, getFileContent: boolean) {
return this.http.get(environment.baseUrl + ‘upload’ + ‘/’ + id , {responseType: ‘blob’ as ‘json’})
.map(res => res);
}
My component function called from the selected item of a FileDownload…
FileDownload(event: any) {
// const blob = await this.callService.getEvidenceFile(event.target.value, true);
// const url = window.URL.createObjectURL(blob);
this.callService.getEvidenceFile(event.target.value, true).subscribe(data => {
var binaryData = [];
binaryData.push(data);
var downloadLink = document.createElement(‘a’);
downloadLink.href = window.URL.createObjectURL(new Blob(binaryData));
document.body.appendChild(downloadLink);
downloadLink.click();
});
}

PhoneGap 3.0.0 - Read locally stored HTML file into the local Safari browser for display purposes on IOS

Good day
I am reading HTML files from an external server via JQuery AJAX call, and storing them on a local IOS 6.0 device with FileWriter. I then read the locally stored files with FileReader and I successfully get the text. What I want to achieve from here, is to take the HTML content from the locally stored file (retrieved via FileReader), and push it into the local Safari Browser on the phone for displaying the HTML page (current target market is iPhone 5). Below is some code. Any ideas how to achieve this? I have tried window.open after installing the InAppBrowser plugin (which I do not really want to use because I want to use Safari) and also returning the text in the onloadend event... document.write is also not ideal as I want to open the file in a new window/tab so that it can be closed to direct the user back to the app when done. I am also not sure if I should read as Binary or Text (assuming TEXT would be the right option because it is not a media file)
Please note that I am new to PhoneGap so my methods used may not reflect Best Practice...
document.addEventListener('deviceready', onDeviceReady, false);
function onDeviceReady () {
var fileName = 'some_file.html';
readerObject.setFileName(fileName);
//Instantiate reader on the file
window.requestFileSystem(LocalFileSystem.PERSISTENT, 0,
readerObject.gotFS, readerObject.fail);
}
// Create reader
var readerObject = {
// Sets the file name to read from
setFileName : function(fileName) {
readerObject.fileName = fileName;
},
// Gets the file name to read from
getFileName : function() {
return readerObject.fileName;
},
// Capture the file system
gotFS : function(fileSystem) {
fileSystem.root.getFile(readerObject.getFileName(), null,
readerObject.gotFileEntry, readerObject.fail);
},
gotFileEntry : function(fileEntry) {
fileEntry.file(readerObject.readData, readerObject.fail);
},
**readData : function(file) {
var reader = new FileReader();
reader.onloadend = function(evt) {
//Return text for streaming into the browser (NOT WORKING)
//return evt.target.result;
//Capture file path
var filePath = file.fullPath+"/"+file.name;
//Open file in new window (NOT WORKING)
//window.open(filePath, '_blank', 'location=yes');
window.open("file:///"+filePath, '_blank', 'location=yes');
};
reader.readAsText(file);
//reader.readAsBinaryString(file);
},**
fail : function(error) {
alert(error.code);
}
}