read zip attachment in visualforce page - salesforce

Hi all I am developing an app on salesforce.
I want to read the content of the file which is inside the zip attachment in visualforce page but without extracting the zip file.
How can I achieve this? Is there any way to do this?

Update for modified question:
Have a look at Handling Office Files and Zip Files in Apex – Part 2 by Andrew Fawcett.
There is a basic Knowledge Article on how to do this with an image that is stored in an Attachment. See How can I Display Base64 Data on page layout?
In this example the AttachmentID is passed via a query string paramemter, but you could look it up however works best for your requirement.
Visualforce page:
<apex:page controller="ViewImage" cache="true">
<img src="data:{!att.ContentType};base64,{!image}" />
</apex:page>
Controller:
public class ViewImage {
public Attachment att {
get {
if (att == null) {
String id = ApexPages.currentPage().getParameters().get('AttachmentID');
att = [SELECT Body, ContentType, Name FROM Attachment WHERE ID = :id];
}
return att;
}
private set;
}
public String image {
get {
return EncodingUtil.Base64Encode(att.body);
}
}
}

Hi all I have achieved this using JSzip library here is my code --
In apex page I have written javascript function --
function viewContent(){
var zip = null;
var zipFileName = null;
var zipFileNames = null;
data = "{!contentAsText}";
zip = new JSZip(data, {base64:true});
zipFileName = 'files.zip';
zipFileNames = [];
for(var zipfileName in zip.files){
zipFileNames.push(zipfileName);
if(zipfileName == 'index.html'){
var file = zip.files[zipfileName];
var data = file.data;
document.getElementById('contentdiv').innerHTML = data;
//var data = JSZipBase64.encode(file.data);
}
}
In controller --
public String contentAsText {get;set;}
List<Attachment> atts = [Select Id, Body from Attachment where name='files.zip' limit 1];
contentAsText = EncodingUtil.base64Encode(atts[0].Body);
This link will help you --
http://andyinthecloud.com/2012/12/09/handling-office-files-and-zip-files-in-apex-part-2/

Related

'ControllerBase.File(byte[], string)' is a method, which is not valid in the given context (CS0119) - in method

I am trying to create an app where user can upload a text file, and gets the altered text back.
I am using React as FE and ASP.NET Core for BE and Azure storage for the database storage.
This is how my HomeController looks like.
I created a separate "UploadToBlob" method, to post the data
public class HomeController : Controller
{
private readonly IConfiguration _configuration;
public HomeController(IConfiguration Configuration)
{
_configuration = Configuration;
}
public IActionResult Index()
{
return View();
}
[HttpPost("UploadFiles")]
//OPTION B: Uncomment to set a specified upload file limit
[RequestSizeLimit(40000000)]
public async Task<IActionResult> Post(List<IFormFile> files)
{
var uploadSuccess = false;
string uploadedUri = null;
foreach (var formFile in files)
{
if (formFile.Length <= 0)
{
continue;
}
// read directly from stream for blob upload
using (var stream = formFile.OpenReadStream())
{
// Open the file and upload its data
(uploadSuccess, uploadedUri) = await UploadToBlob(formFile.FileName, null, stream);
}
}
if (uploadSuccess)
{
//return the data to the view, which is react display text component.
return View("DisplayText");
}
else
{
//create an error component to show there was some error while uploading
return View("UploadError");
}
}
private async Task<(bool uploadSuccess, string uploadedUri)> UploadToBlob(string fileName, object p, Stream stream)
{
if (stream is null)
{
try
{
string connectionString = Environment.GetEnvironmentVariable("AZURE_STORAGE_CONNECTION_STRING");
// Create a BlobServiceClient object which will be used to create a container client
BlobServiceClient blobServiceClient = new BlobServiceClient(connectionString);
//Create a unique name for the container
string containerName = "textdata" + Guid.NewGuid().ToString();
// Create the container and return a container client object
BlobContainerClient containerClient = await blobServiceClient.CreateBlobContainerAsync(containerName);
string localPath = "./data/";
string textFileName = "textdata" + Guid.NewGuid().ToString() + ".txt";
string localFilePath = Path.Combine(localPath, textFileName);
// Get a reference to a blob
BlobClient blobClient = containerClient.GetBlobClient(textFileName);
Console.WriteLine("Uploading to Blob storage as blob:\n\t {0}\n", blobClient.Uri);
FileStream uploadFileStream = File.OpenRead(localFilePath);
await blobClient.UploadAsync(uploadFileStream, true);
uploadFileStream.Close();
}
catch (StorageException)
{
return (false, null);
}
finally
{
// Clean up resources, e.g. blob container
//if (blobClient != null)
//{
// await blobClient.DeleteIfExistsAsync();
//}
}
}
else
{
return (false, null);
}
}
}
but the console throws errors, saying "'ControllerBase.File(byte[], string)' is a method, which is not valid in the given context (CS0119)"
And because of this error, another error follows "'HomeController.UploadToBlob(string, object, Stream)': not all code paths return a value (CS0161)"
my questions are
Is it a better idea to create a separate method like I did?
how can I resolve the issue regarding the "File" being valid inside of the UploadToBlob method?
If I want to add the file type validation, where should it happen? t.ex. only text file is alid
If I want to read the text string from the uploaded text file, where should I call the
string contents = blob.DownloadTextAsync().Result;
return contents;
How can I pass down the "contents" to my react component? something like this?
useEffect(() => {
fetch('Home')
.then(response => response.json())
.then(data => {
setForcasts(data)
})
}, [])
Thanks for helping this super newbie with ASP.NET Core!
1) It is ok to put uploading into separate method, it could also be put into a separate class for handling blob operations
2) File is the name of one of the controllers methods, if you want to reference the File class from System.IO namespace, you need to fully qualify the name
FileStream uploadFileStream = System.IO.File.OpenRead(localFilePath);
To the other compile error, you need to return something from the UploadToBlob method, now it does not return anything from the try block
3) File type validation can be put into the controller action method
4) it depends on what you plan to do with the text and how are you going to use it. Would it be a new action of the controller (a new API endpoint)?
5) you could create a new API endpoint for downloading files
UPDATE:
For word replacement you could use a similar method:
private Stream FindMostFrequentWordAndReplaceIt(Stream inputStream)
{
using (var sr = new StreamReader(inputStream, Encoding.UTF8)) // what is the encoding of the text?
{
var allText = sr.ReadToEnd(); // read all text into memory
// TODO: Find most frequent word in allText
// replace the word allText.Replace(oldValue, newValue, stringComparison)
var resultText = allText.Replace(...);
var result = new MemoryStream();
using (var sw = new StreamWriter(result))
{
sw.Write(resultText);
}
result.Position = 0;
return result;
}
}
it would be used in your Post method this way:
using (var stream = formFile.OpenReadStream())
{
var streamWithReplacement = FindMostFrequentWordAndReplaceIt(stream);
// Upload the replaced text:
(uploadSuccess, uploadedUri) = await UploadToBlob(formFile.FileName, null, streamWithReplacement);
}
You probably have this method inside MVC controller in which File method exists. Add in your code System.IO.File instead of File

update a already inserted image in database using java spring

I am tying like this , I want to use same method for inserting and updating, also same form to insert and update. please help me.. this is my controller, it is working fine if I choose new image while updating but if I didnot select image while updating and only update other details then image updated to null in database..
public ModelAndView addOrUpdateFoodItems(#RequestParam(name = "file")CommonsMultipartFile file,
#RequestParam(name = "food_name")String food_name,
#RequestParam(name = "food_type")String food_type,
#RequestParam(name = "food_tags")String food_tags,
#RequestParam(name = "food_desription")String food_desription,
#RequestParam(name = "protein_intake")String protein_intake,
#RequestParam(name = "calorie_intake")String calorie_intake,
#RequestParam(name = "carbs_intake")String carbs_intake,ModelAndView model, HttpServletRequest request){
FoodItemDetails foodItemDetails;
foodItemDetails= (FoodItemDetails) request.getSession().getAttribute("FoodItemDetails");
if(foodItemDetails==null){
foodItemDetails=new FoodItemDetails();
}else{
System.out.println(foodItemDetails.getFood_name());
}
foodItemDetails.setFood_name(food_name);
foodItemDetails.setFood_type(food_type);
foodItemDetails.setFood_tags(food_tags);
foodItemDetails.setFood_desription(food_desription);
foodItemDetails.setProtein_intake(protein_intake);
foodItemDetails.setCalorie_intake(calorie_intake);
foodItemDetails.setCarbs_intake(carbs_intake);
if(file.getOriginalFilename()!=null){
foodItemDetails.setFood_item_image(file.getBytes());
foodItemDetails.setFood_item_image_name(file.getOriginalFilename());}
else{
foodItemDetails.setFood_item_image_name(foodItemDetails.getFood_item_image_name());
foodItemDetails.setFood_item_image(foodItemDetails.getFood_item_image());
}
boolean done= trainerService.saveOrUpdateFoodItems(foodItemDetails);
model.setViewName("redirect:/trainer/addFoodItems");
return model;
}

upload multiple files , enctype=“multipart/form-data”

I want to upload multiple files to the controller but its taking only one.
I am using multipart for file transfer.
How to get the multiple files to the controller side.
I am not able to access bytes and filename. Its throwing errors,
#RequestMapping(value = "/home/step38/uploadReport", method = RequestMethod.POST)
public ModelAndView uploadReport(
#RequestParam(value = "fileName") List<MultipartFile> files,
#RequestParam(value = "pLogId") String pLogId,
HttpServletRequest request, HttpSession session)
{
int applicationNameId = 0;
String fileName;
String typeOption = "Raw Particle Data";
for(MultipartFile file:files)
fileName = file.getOriginalFilename();
logger.debug("step3.1 upload particle count -- Start");
ModelAndView modelAndView = createModelAndView(ToogleStep.step38);
setCurrentStep(session, modelAndView, ToogleStep.step38);
String view = "redirect:/home/step38";
modelAndView.setViewName(view);
try
{
User user = (User) session.getAttribute(Constants.USER_DB);
Project current_project = (Project) session.getAttribute(Constants.PROJECT);
Credential credential = (Credential) session.getAttribute(Constants.AUTH_USER);
boolean checkOK = true;
if (current_project != null && SystemUtils.projectEditable(current_project, credential))
{
long projectId = current_project.getId();
if(checkOK)
{
byte[] bytes = file.getBytes();
HashMap<String,String> options= new HashMap<String,String>();
//added pLogId in the options(this will contain demoToogleFileInfoId)
options.put(ToogleReportDataConstants.TTL_PROCESS_LOG_ID_OPTION,pLogId);
String toogleFileId = reportService.uploadReport(user, projectId, fileName, typeOption, bytes, applicationNameId, options);
}
}
}
You are not looping through at the right location.
try looping it after you have your modelAndView(view)
int applicationNameId = 0;
String typeOption = "Raw Particle Data";
ModelAndView modelAndView = createModelAndView(ToogleStep.step38);
setCurrentStep(session, modelAndView, ToogleStep.step38);
String view = "redirect:/home/step38";
modelAndView.setViewName(view);
// upload multiple files.
for(MultipartFile file:files){
String fileName= file.getOriginalFilename();
and then you will be able to access bytes and filename. Give this a try.
Atleast by looking at your problem I can suggest and if you can give more specific error, I can help.

webapi MVC4 how to get folder files directory to display data

hi guys i able to get the data from my database API. but how do i get the folder files directory example /upload/activity/ ??
public class APIActivityController : ApiController
{
// var files = db.activities.GetFiles().ToList();
private istellarEntities db = new istellarEntities();
public IList<activity2> GetAllCategories()
{
IList<activity> lstAct = db.activities.ToList();
List<activity2> lstReturnList = new List<activity2>();
foreach (activity a in lstAct)
{
Models.activity2 act = new activity2();
act.ActivityID = a.ActivityID;
act.ActivityName = a.ActivityName;
act.Description = a.Description;
act.ImageURL = a.ImageURL;
lstReturnList.Add(act);
}
return lstReturnList;
}
// var files = db.activities.GetFiles().ToList();
static void DirSearch(string sDir)
here is my code, but i am missing something to get the list of directories any help guys? i know i shouldn't use void, maybe a list instead??
try
{
foreach (string d in Directory.GetDirectories(sDir))
{
foreach (string f in Directory.GetFiles(d))
{
Console.WriteLine(f);
}
DirSearch(d);
}
}
catch (System.Exception excpt)
{
Console.WriteLine(excpt.Message);
}
To get the physical folder path of a virtual path from your code like /upload/activity you can use the following code
string pathToFiles = Server.MapPath("/upload/activity");

url sharepoint list camlquery

I'm trying to collect my url and the description of the url stored in a column of a list from sharepoint and i don't know how to collect the URL value.
This is my code :
var queryResultSaleListItems = clientContext.LoadQuery(listData);
clientContext.ExecuteQuery();
//Read the Data into the Object
var TipsList = from Tips in queryResultSaleListItems
select Tips;
ObservableCollection<Tips> colTips = new ObservableCollection<Tips>();
//Read Every List Item and Display Data into the DataGrid
foreach (SPSClient.ListItem item in TipsList)
{
var tips = new Tips();
tips.TitleTip = item.FieldValues.Values.ElementAt(1).ToString();
tips.App = item.FieldValues.Values.ElementAt(4).ToString();
//should collect the url
tips.URL = item.FieldValues.Values.ElementAt(5).ToString();
//should collect the description of the url
tips.URLdesc = item.FieldValues.Values.ElementAt(5).ToString();
colTips.Add(tips);
}
ListboxTips.DataContext = colTips;
In my expression its >
((Microsoft.SharePoint.Client.FieldUrlValue)(item.FieldValues.Values.ElementAt(5))).Url
((Microsoft.SharePoint.Client.FieldUrlValue)(item.FieldValues.Values.ElementAt(5))).Description
Thanks for your help,
Use FieldUrlValue for getting hyperlink field in Client Object Model.
Use Following Code:
string server = "siteURL";
var ctx = new ClientContext(server);
var web = ctx.Web;
var list = web.Lists.GetByTitle("CustomList");
var listItemCollection = list.GetItems(CamlQuery.CreateAllItemsQuery());
ctx.Load(listItemCollection);
ctx.ExecuteQuery();
foreach (Microsoft.SharePoint.Client.ListItem listItem in listItemCollection)
{
string acturlURL = ((FieldUrlValue)(listItem["URL"])).Url.ToString(); // get the Hyperlink field URL value
string actdesc = ((FieldUrlValue)(listItem["URL"])).Description.ToString(); // get the Hyperlink field Description value
}

Resources