Convert blob to images and save it to local folder - Apex - salesforce

I'm able to read blob from the richtext field now need to save it as .jgp/png into my local folder
Matcher imgMatcher = Pattern.compile( '<img(.+?)>' ).matcher(con.Photo__c);
String imageURL = imageTag.substringBetween( ' src="', '"' );
String decodedURL = imageURL.unescapeHtml4();
PageReference page = new PageReference( decodedURL );
Blob bodyBlob = page.getContent();
//something like this
File file=new File('c://myimages');
image img=new image(bodyBlob);
img.fomrat='jpg';
img.title='myphoto';
file.save(img);
so it stores as image in my local folder. is this possible using apex(salesforce)

Salesforce cannot write to your file system. You have a few options, you can save to an Attachment record or Document record and download it from there, or you can expose the file through a visualforce page that lets you download the file as an attachment if you dont want to have it stored in salesforce at all. something along the lines of:
<apex:page contentType="img/jpg" extensions="xxx">{!image}</apex:page>

This is how i achieved, once saved to salesforce folder from there i downloaded the images, hope it helps someone.
Matcher imgMatcher = Pattern.compile( '<img(.+?)>' ).matcher(con.Photo__c);
String imageURL = imageTag.substringBetween( ' src="', '"' );
String decodedURL = imageURL.unescapeHtml4();
PageReference page = new PageReference( decodedURL );
Blob bodyBlob = page.getContent();
Document doc=new Document();
doc.Body=bodyBlob;
doc.FolderId='salesforce folder Id';
doc.Name=con.name;
doc.Type='jpg';
Insert doc;

Related

Save as .PARQUET file in Logic App workflow

How can I save the output file from Run query and list results in a .PARQUET file format.
This is my current workflow.
My Logic App is working, But the file .parquet created are not valid every time I view it on Apache Parquet Viewer
Can someone help me on this matter. Thank you!
Output:
I see that you are trying to add .parquet to the csv file you are receiving but that's not how it will be converted to parquet file.
One of the workarounds that you can try is to get the csv file and then add Azure function which can convert into parquet file and then adding the azure function to logic app.
Here is the function that worked for me:
BlobServiceClient blobServiceClient = new BlobServiceClient("<YOUR CONNECTION STRING>");
BlobContainerClient containerClient = blobServiceClient.GetBlobContainerClient("<YOUR CONTAINER NAME>");
BlobClient blobClient = containerClient.GetBlobClient("sample.csv");
//Download the blob
Stream file = File.OpenWrite(#"C:\Users\<USER NAME>\source\repos\ParquetConsoleApp\ParquetConsoleApp\bin\Debug\netcoreapp3.1\" + blobClient.Name);
await blobClient.DownloadToAsync(file);
Console.WriteLine("Download completed!");
file.Close();
//Read the downloaded blob
Stream file1 = new FileStream(blobClient.Name, FileMode.Open);
Console.WriteLine(file1.ReadToEnd());
file1.Close();
//Convert to parquet
ChoParquetRecordConfiguration csv = new ChoParquetRecordConfiguration();
using (var r = new ChoCSVReader(#"C:\Users\<USER NAME>\source\repos\ParquetConsoleApp\ParquetConsoleApp\bin\Debug\netcoreapp3.1\" + blobClient.Name))
{
using (var w = new ChoParquetWriter(#"C:\Users\<USER NAME>\source\repos\ParquetConsoleApp\ParquetConsoleApp\bin\Debug\netcoreapp3.1\convertedParquet.parquet"))
{
w.Write(r);
w.Close();
}
}
after this step you can publish to your azure function and add the Azure function connector to your logic app
You can skip the first 2 steps (i.e.. Read and Download the blob) and get the blob directly from logic app and send it to your azure function and follow the same method as above. The generated parquet file will be in this path.
C:\Users\<USERNAME>\source\repos\ParquetConsoleApp\ParquetConsoleApp\bin\Debug\netcoreapp3.1\convertedParquet.parquet
Here convertedParquet.parquet is the name of the parquet file. Now you can read the converted parquet file in Apache Parquet reader.
Here is the output

How to save Base64 String to file and view it using Flutter

I need to download and view file (if possible, for Image, PDF, etc) using Flutter.
My problem is, the file that I want to download is Base64 String.
How can I achieve that using Flutter??
Following is the code snippet to decode base64 string and save it as a file on the local device. please note in terms of viewing files, image and pdf would require different libraries.
Future<String> _createFileFromString() async {
final encodedStr = "put base64 encoded string here";
Uint8List bytes = base64.decode(encodedStr);
String dir = (await getApplicationDocumentsDirectory()).path;
File file = File(
"$dir/" + DateTime.now().millisecondsSinceEpoch.toString() + ".pdf");
await file.writeAsBytes(bytes);
return file.path;
}
Google Chrome does not let open tab with Url base64 encode, like "data:application/pdf;base64,JVBERi0xLjQKJeLj..." with javascript, so you can not open url with url_launcher, but you can download file.
Here is my code:
import 'dart:html' as html;
...
Future<void> downloadFile() {
final urlString = "data:application/pdf;base64,JVBERi0xLjQKJeLj...";
html.AnchorElement anchorElement = html.AnchorElement(href:urlString);
anchorElement.download = urlString;
anchorElement.click();
}

Retrieve uploaded file attributes from Spring MultipartFile

I am uploading a file using Spring MultipartFile. I need to store the uploaded file attributes like creation date and modified date. Currently I am using following approach:
File dest = new File(uploadfile.getOriginalFilename());
dest.createNewFile();
FileOutputStream fos = new FileOutputStream(dest);
fos.write(uploadfile.getBytes());
fos.close();
Path filee = dest.toPath();
BasicFileAttributes attr = Files.readAttributes(filee, BasicFileAttributes.class);
System.out.println("creationTime: " + attr.creationTime());
System.out.println("lastAccessTime: " + attr.lastAccessTime());
System.out.println("lastModifiedTime: " + attr.lastModifiedTime());
where uploadfile is the object of spring boot MultipartFile.
Referred links :
How to convert a multipart file to File?
Get java.nio.file.Path object from java.io.File
Determine file creation date in Java
The issue is that I am getting creation date and modified date as the current date only and probably the reason is that the new file object is resetting these values. How can I get the attributes of the original uploaded file?
The file meta data (like your creationTime, lastAccessTime, lastModifiedTime) is not part of the file, but the filesystem. Thus by uploading a file you only get the file and not the additional (meta) data that is managed by the filesystem.
You could add the last modified date to the upload form with the help of the File API (access and creation are not supported), but these can be manipulated by the user and thus you cannot trust them, if that is not a problem for you here an example from: https://developer.mozilla.org/en-US/docs/Web/API/File/lastModified
html:
<!-- inside your form -->
<input type="file" multiple id="fileInput">
javascript:
const fileInput = document.getElementById('fileInput');
fileInput.addEventListener('change', function(event) {
// files is a FileList object (similar to NodeList)
const files = event.target.files;
for (let i = 0; i < files.length; i++) {
const date = new Date(files[i].lastModified);
alert(files[i].name + ' has a last modified date of ' + date);
// TODO add the date as a hidden input to your form
}
});

Google apps script, openByURL returns missing file?

I've been trying to figure out why part of my Google App script doesn't work, but I've failed to come up with an answer.
The script is downloading an attachment, CSV, from an email in Gmail and stores in with a specific name in a specific folder - this works perfectly fine.
But then I want to edit the CSV, and this is where I run into problems.
var newFolderIterator = DriveApp.getFoldersByName(destinationFolderName)
var newFolderId, myFileName, myFileId
while(newFolderIterator.hasNext()) {
newFolderId = newFolderIterator.next().getId()
var newFileList = DriveApp.getFolderById(newFolderId).getFiles()
while(newFileList.hasNext()) {
myFileName = newFileList.next()
myFileId = myFileName.getId()
var myFileURL = myFileName.getUrl()
Logger.log(myFileName.getId() + " " + myFileName.getName()) //Logs the ID and Name
Logger.log(myFileURL) //Logs the URL
var ss = SpreadsheetApp.openById(myFileName.getId()) //Error, cannot find the ID (error message: perhaps it's missing?)
}
}
I've tried using the openByURL as well, with the same error message.
Probably really easy to fix, any hints and tips is appreciated.
Thanks
The problem here is you are uploading a CSV but attempting to open it with SpreadsheetApp. SpreadsheetApp can only open Google Sheets documents, and your CSV is not automatically converted.
The CSV must first be converted to a Google Sheets document before you can access it with SpreadsheetApp.
You may be able to do this on upload, but I haven't tried this personally. This question looks relevant:
How to automatically import data from uploaded CSV or XLS file into Google Sheets

How to download a pdf file in Composite c1

I'm trying to implement a functionality that enables a user to download a PDF on clicking on a hyper-link. What i've done is, I've created a global datatype Publications which takes values "Description" and "PDF DOC" and I've a user control with a hyper-link which binds the description as its text.
LinkButton1.Text = details.Description;
Composite.Data.DataReference<IMediaFile> i = new Composite.Data.DataReference<IMediaFile>((details as A.DataTypes.Publications).PdfDoc);
string filePath = "/media(" + i.Data.Id + ")";
and on the click on the link button I've...
Response.ContentType = "Application/pdf";
Response.AppendHeader("Content-Disposition", "attachment; filename=Test_PDF.pdf");
Response.TransmitFile(filePath );
Response.End();
this is showing an error saying "could not find file", any idea why?
It looks like you are trying to use the C1 syntax for media files at a place where the C1 page renderer never replaces it with the actual url of the file. So you end up passing something like /media(b5354eba-3f69-4885-9eba-74576dff372d) to the Response.TransmitFile() function, which will not work because that is not a valid file path.
If you use this syntax on a C1 page, the page renderer will replace it with the real url of the file.
My advise would be to build this URL yourself and just link to it, instead of using TransmitFile. A simple redirect will suffice if the file is open for public access. If it is lying acessible on the web server already, there is not much point in using Response.TransmitFile and fetching it and writing it in the outputstream.
Try look at the DownloadFoldersAsZip package (https://bitbucket.org/burningice/compositec1contrib/src/4c31794cd46c/DownloadFoldersAsZip?at=default) which has this functionality. The main issue with your code is that you make the assumption of where the files are stored. You can't do that with the C1 Media Archive, since files can be either local, in a database, in Azure Blob storage or just a random place on the internet.
Instead you should use the GetReadStream() extension method of your IMediaFile instance. This will give you a stream which you can copy unto your Response.ResponseStream
See here for an example: https://bitbucket.org/burningice/compositec1contrib/src/4c31794cd46cb03dd0b0ee830b83204753355b03/DownloadFoldersAsZip/Web/GenerateZipHandler.cs?at=default#cl-145
solved it, just needed to give....string filePath = "~/media({" + i.Data.Id + "})"; instead of string filePath = "/media(" + i.Data.Id + ")";
You can also use this code
Composite.Data.DataReference i = new Composite.Data.DataReference((details as A.DataTypes.Publications).PdfDoc)
This gives the media file reference
string fileName = "/App_Data/Media/" + i.Data.Id.ToString();
this.Response.AddHeader("content-disposition", string.Format(
"attachment;filename=download.pdf", Path.GetFileName(fileName)));
this.Response.ContentType = "application/pdf";
this.Response.WriteFile(this.Server.MapPath(fileName));
This can get the file Downloaded as download.pdf

Resources