Change this from sync to async webrequests - asp.net

I ahve been diggin the net for some time now, not finding code examples that help me through my problem.. I have looked at example code but I'm still not "getting" it...
I have read up on,
http://msdn.microsoft.com/en-us/library/aa480507.aspx and
http://msdn.microsoft.com/en-us/library/dd781401.aspx
But I cant seem to get it to work..
Im using HTMLAGILITYPACK
Today I make up to 20 webrequests,
After a request has finished, result is added to dictionary, after that a method searches it for the information, if found the code exits if not it makes another webrequest , until it caps at 20. I need to be able to exit all threads async calls when everything is found.
It goes like this
public void FetchAndParseAllPages()
{
PageFetcher fetcher = new PageFetcher();
for (int i = 0; i < _maxSearchDepth; i += _searchIncrement)
{
string keywordNsearch = _keyword + i;
ParseHtmldocuments(fetcher.GetWebpage(keywordNsearch));
//this checks if the information was found or not, if
//found stop exit and add to database
if (GetPostion() != 201)
{ //ADD DATA TO DATABASE
InsertRankingData(DocParser.GetSearchResults(), _theSearchedKeyword);
return;
}
}
}
This is inside the class that fetches the page
public HtmlDocument GetWebpage(string urlToParse)
{
System.Net.ServicePointManager.Expect100Continue = false;
HtmlWeb htmlweb = new HtmlWeb();
htmlweb.PreRequest = new HtmlAgilityPack.HtmlWeb.PreRequestHandler(OnPreRequest);
HtmlDocument htmldoc = htmlweb.Load(#"urlToParse", "38.69.197.71", 45623, "PORXYUSER", "PROXYPASSWORD");
return htmldoc;
}
public bool OnPreRequest(HttpWebRequest request)
{
// request.UserAgent = RandomUseragent();
request.KeepAlive = false;
request.Timeout = 100000;
request.ReadWriteTimeout = 1000000;
request.ProtocolVersion = HttpVersion.Version10;
return true; // ok, go on
}
How can I make this async and make it really quick with threads? Or should i even use threads when doing it async?

Okay I solved it! At least I think so! Execution time went down to around seven seconds. It took me about 30 secs to do that without async.
Here my code for future reference. EDIT I used a console project to test the code. Also I'm using html agilitypack. This is my way of doing it, any tips on how to further optimize this would be cool to see.
public delegate HtmlDocument FetchPageDelegate(string url);
static void Main(string[] args)
{
System.Net.ServicePointManager.DefaultConnectionLimit = 10;
FetchPageDelegate del = new FetchPageDelegate(FetchPage);
List<HtmlDocument> htmllist = new List<HtmlDocument>();
List<IAsyncResult> results = new List<IAsyncResult>();
List<WaitHandle> waitHandles = new List<WaitHandle>();
DateTime start = DateTime.Now;
for(int i = 0; i < 200; i += 10)
{
string url = #"URLSTOPARSE YOU CHANGE IT HERE READ FROM LIST OR ANYTHING";
IAsyncResult result = del.BeginInvoke(url, null, null);
results.Add(result);
waitHandles.Add(result.AsyncWaitHandle);
}
WaitHandle.WaitAll(waitHandles.ToArray());
foreach (IAsyncResult async in results)
{
FetchPageDelegate delle = (async as AsyncResult).AsyncDelegate as FetchPageDelegate;
htmllist.Add(delle.EndInvoke(async));
}
Console.ReadLine();
}
static HtmlDocument FetchPage(string url)
{
HtmlWeb htmlweb = new HtmlWeb();
HtmlDocument htmldoc = htmlweb.Load(url);
return htmldoc;
}

Related

Problem with getting the random photo from Firebase by usage of async Tasks and async UnityWebRequest

I've created a call to Firebase to get the random photo (since we have categories of photos, first I'm trying to get random category, then random photo from it). After that I want to make async UnityWebRequest to get the photo and add it as a texture. The code gets to the inside of the Task but the call to database is never executed. I tried the code to get the image separately and it worked just fine. I also tried using delegate and action, but didn't help much. I'm still pretty newbie to C# and Unity, so my code isn't that good. Will appreciate all the feedback.
I tried the code to get the image separately and it worked just fine. I also tried using delegate and action, but didn't help much. I'm still pretty newbie to C# and Unity, so my code isn't that good. Will appreciate all the feedback.
//Getting the random photo
async Task GetRandomPhoto(){
await photosDbReference.GetValueAsync().ContinueWith(task =>{
List<string> snapshotList = new List<string>();
List<string> snapsnotList2 = new List<string>();
if(task.IsCompleted){
int catNumber = Convert.ToInt32(task.Result.ChildrenCount);
System.Random rnd = new System.Random();
int randCat = rnd.Next(0, catNumber);
foreach (DataSnapshot snapshot in task.Result.Children)
{
snapshotList.Add(snapshot.Key.ToString());
}
photosDbReference.Child(snapshotList[randCat]).GetValueAsync().ContinueWith(task2 =>{
if(task2.IsCompleted){
int photosNumber = Convert.ToInt32(task2.Result.ChildrenCount);
System.Random rnd2 = new System.Random();
int randPhoto = rnd.Next(0, photosNumber);
foreach(DataSnapshot snap2 in task2.Result.Children){
snapsnotList2.Add(snap2.Child("Dblink").Value.ToString());
}
string photoLink = snapsnotList2[randPhoto];
}
});
}
});
}
//Trying to set the photo as a texture
public async void PutTheTexture(string url){
Texture2D texture = await GetTexture(url);
myImage.texture = texture;
}
public async Task<Texture2D> GetTexture(string url){
Debug.Log("Started");
UnityWebRequest www = UnityWebRequestTexture.GetTexture(url);
Debug.Log("Sending request: " + url);
var asyncOp = www.SendWebRequest();
Debug.Log("Request sent");
while( asyncOp.isDone==false )
{
await Task.Delay( 1000/30 );
}
if( www.isNetworkError || www.isHttpError )
{
#if DEBUG
Debug.Log( $"{ www.error }, URL:{ www.url }" );
#endif
return null;
}
else
{
return DownloadHandlerTexture.GetContent( www );
}
}
The code gets to the Debug.Log("Started"); inside the Task but apparently the request is never send.
I can't quite tell how your two blocks of code go together, but what I will point out is that .ContinueWith will not continue in Unity's main thread. My suspicion is that the continuation is kicking off the GetTexture via a mechanism I'm not seeing.
As far as I can tell, async/await should always stay in your current execution context but perhaps the Continuations are causing your logic to execute outside of the Unity main thread.
Since you're using Firebase, this would be super easy to test by replacing ContinueWith with the extension method ContinueWithOnMainThread. If this doesn't help, you can generally swap out async/await logic with continuations on tasks or fairly easily convert the above example to use purely coroutines:
//Getting the random photo
void GetRandomPhoto(){
photosDbReference.GetValueAsync().ContinueWithOnMainThread(task =>
{
List<string> snapshotList = new List<string>();
List<string> snapsnotList2 = new List<string>();
if(task.IsCompleted){
int catNumber = Convert.ToInt32(task.Result.ChildrenCount);
System.Random rnd = new System.Random();
int randCat = rnd.Next(0, catNumber);
foreach (DataSnapshot snapshot in task.Result.Children)
{
snapshotList.Add(snapshot.Key.ToString());
}
photosDbReference.Child(snapshotList[randCat]).GetValueAsync().ContinueWithOnMainThread(task2 =>{
if(task2.IsCompleted){
int photosNumber = Convert.ToInt32(task2.Result.ChildrenCount);
System.Random rnd2 = new System.Random();
int randPhoto = rnd.Next(0, photosNumber);
foreach(DataSnapshot snap2 in task2.Result.Children){
snapsnotList2.Add(snap2.Child("Dblink").Value.ToString());
}
string photoLink = snapsnotList2[randPhoto];
}
});
}
});
}
public delegate void GetTextureComplete(Texture2D texture);
private void Completion(Texture2D texture) {
myImage.texture = texture;
}
//Trying to set the photo as a texture
public void PutTheTexture(string url){
GetTexture(url, Completion);
}
public IEnumerator GetTexture(string url, GetTextureComplete completion){
Debug.Log("Started");
UnityWebRequest www = UnityWebRequestTexture.GetTexture(url);
Debug.Log("Sending request: " + url);
var asyncOp = www.SendWebRequest();
Debug.Log("Request sent");
yield return asyncOp;
if( www.isNetworkError || www.isHttpError )
{
#if DEBUG
Debug.Log( $"{ www.error }, URL:{ www.url }" );
#endif
completion(null);
}
else
{
completion(DownloadHandlerTexture.GetContent(www));
}
}
(you can do better than my example, and I haven't verified that it runs. Just a quick pass)
Big Thank You to everybody who tried to help! I finally found the way to solve the issue. I changed my async Task to async Task < "Dictionary" > and made it return the dict wilth all the data of the random photo (label, link, user). Then I created async void in which I wrote:
Dictionary photoData = await GetRandomPhoto();
From there it was very easy.

Crystal report method not found

I made a feedback project. I made it on ASP.NET MVC 5 it also has crystal reports. reports were working fine, but suddenly they stopped to work. I don't what happened with them. but since last week I tried hard to find solution but unfortunately could not get the right one who solved the solution. I downloaded different run times but all went vain. this is the bottom line of error.
"Method not found: 'CrystalDecisions.ReportAppServer.DataDefModel.PropertyBag CrystalDecisions.ReportAppServer.ReportDefModel.ISCRExportOptions.get_ExportOptionsEx()'"
this is the code:
public CrystalReportFeedback UserFeedbackDateWise(FeedbackReport be){
if (Session["CurrentUser"] != null && Convert.ToInt32(Session["User_Id"]) != 0)
{
string reportPath = Path.Combine(Server.MapPath("~/Reports"), "UserFeedbackReport.rpt");
if (ModelState.IsValid)
{
be.FromDate = Convert.ToDateTime(TempData["UserFromDate"]);
be.ToDate = Convert.ToDateTime(TempData["UserToDate"]);
be.User_Id = Convert.ToInt32(Session["User_Id"]);
}
return new CrystalReportFeedback(reportPath, be);
}
else
{
return null;
//new CrystalReportFeedback(reportPath, be);
}
}
Init of the report :
public CrystalReportFeedback(string reportPath, FeedbackReport be)//, object dataSet)
{
//int[] array;
string strConnect = Convert.ToString(System.Configuration.ConfigurationManager.ConnectionStrings["TSC"]);
SqlConnectionStringBuilder builder = new SqlConnectionStringBuilder(strConnect);
string _username = builder.UserID;
string _pass = builder.Password;
string _server = builder.DataSource;
string _database = builder.InitialCatalog;
ReportDocument reportDocument = new ReportDocument();
//
reportDocument.Load(reportPath);
reportDocument.SetDatabaseLogon(_username, _pass, _server, _database);
if (be.Region_Id != 0)
{
reportDocument.SetParameterValue("#Region_Id", be.Region_Id);
}
if (be.User_Id != 0)
{
reportDocument.SetParameterValue("#User_Id", be.User_Id);
}
reportDocument.SetParameterValue("#FromDate", be.FromDate);
reportDocument.SetParameterValue("#ToDate", be.ToDate);
//reportDocument.ExportToDisk(ExportFormatType.PortableDocFormat, "C:\report.pdf");
_contentBytes = StreamToBytes(reportDocument.ExportToStream(ExportFormatType.PortableDocFormat));
}
Export method :
public override void ExecuteResult(ControllerContext context)
{
var response = context.HttpContext.ApplicationInstance.Response;
response.Clear();
response.Buffer = false;
response.ClearContent();
response.ClearHeaders();
response.Cache.SetCacheability(HttpCacheability.Public);
response.ContentType = "application/pdf";
using (var stream = new MemoryStream(_contentBytes))
{
stream.WriteTo(response.OutputStream);
stream.Flush();
}
}
private static byte[] StreamToBytes(Stream input)
{
byte[] buffer = new byte[16 * 1024];
using (MemoryStream ms = new MemoryStream())
{
int read;
while ((read = input.Read(buffer, 0, buffer.Length)) > 0)
{
ms.Write(buffer, 0, read);
}
return ms.ToArray();
}
}
Hope that I will get my solution at earliest.
this is modified code:
[HttpGet]
public FileResult UserFeedbackDateWise(FeedbackReport be)
{
if (Session["CurrentUser"] != null && Convert.ToInt32(Session["User_Id"]) != 0)
{
string reportPath = Path.Combine(Server.MapPath("~/Reports"), "UserFeedbackReport.rpt");
if (ModelState.IsValid)
{
be.FromDate = Convert.ToDateTime(TempData["UserFromDate"]);
be.ToDate = Convert.ToDateTime(TempData["UserToDate"]);
be.User_Id = Convert.ToInt32(Session["User_Id"]);
}
string strConnect = Convert.ToString(System.Configuration.ConfigurationManager.ConnectionStrings["TSC"]);
SqlConnectionStringBuilder builder = new SqlConnectionStringBuilder(strConnect);
string _username = builder.UserID;
string _pass = builder.Password;
string _server = builder.DataSource;
string _database = builder.InitialCatalog;
ReportDocument reportDocument = new ReportDocument();
//
reportDocument.Load(reportPath);
reportDocument.SetDatabaseLogon(_username, _pass, _server, _database);
if (be.Region_Id != 0)
{
reportDocument.SetParameterValue("#Region_Id", be.Region_Id);
}
if (be.User_Id != 0)
{
reportDocument.SetParameterValue("#User_Id", be.User_Id);
}
reportDocument.SetParameterValue("#FromDate", be.FromDate);
reportDocument.SetParameterValue("#ToDate", be.ToDate);
Stream stream = reportDocument.ExportToStream(CrystalDecisions.Shared.ExportFormatType.PortableDocFormat);
//Here i have my stream with my pdf report, i just create a new FileStreamResult and return it to my client like that :
FileStreamResult myfile = new FileStreamResult(stream, "application/pdf");
return myfile;
//new CrystalReportFeedback(reportPath, be);
}
else
{
return null;
//new CrystalReportFeedback(reportPath, be);
}
}
This isn't a coding issue, it's a runtime issue. The version of the crystal runtime or the bitness of your application.
One thing to try first is to upgrade both your development version and ensure you're running the same version in production. See https://apps.support.sap.com/sap/support/knowledge/public/en/2148492 for more details
It says:
Compile your application either to 'X86 mode' or 'X64 mode'
Install the particular versions of runtimes on deployment machine.
i.e. If the application is compiled as 32 bit, then install the 32bit runtimes.
I'll try my best to help you exporting your report, but your post is not very clear. For your next post try to be very specific and provide as much information as you can.
I currently made a MVC project and export a crystalreport report from my controller to my client.
I think that your ExecuteResult method can work, but working with the httpcontext is useless, Crystalreport and .NET provide some useful methods to do the same.
So i'll show you how i create and export my report so you can copy / paste and modify your code.
Here is my controller method, called from a button :
[HttpGet]
public FileResult InitReport()
{
//I create my report here
FileImportReport rptH = new FileImportReport();
// Some configuration on the report, datasource, databaselogon .. etc
...
//
//Then I export my report to a pdf stream like that :
Stream stream = rptH.ExportToStream(CrystalDecisions.Shared.ExportFormatType.PortableDocFormat);
//Here i have my stream with my pdf report, i just create a new FileStreamResult and return it to my client like that :
FileStreamResult myfile = new FileStreamResult(stream, "application/pdf");
return myfile;
}
My method is called from a button but it can work like you want, or the file can be saved in any known path.
You can test to reproduce my code, in your CrystalReportFeedback method use my code with your reportDocument object, you don't need to use your StreamToBytes method.
Regards,
EDIT : Useful links with your error :
Crystal Reports exception in Visual Studio 2013
https://www.arcanadev.com/support/kb/K00000499.aspx

Generating PDFs using Phantom JS on .NET applications

I have been looking into phantomJS and looks like it could be a great tool to use generating PDFs. I wonder if anyone have successfully used it for their .NET applications.
My specific question is: how would you use modules like rasterize.js on the server, receive requests and send back generated pdfs as a response.
My general question is: is there any best practice for using phantomJS with .NET Applications. What would be the best way to achieve it?
I am fairly new in .NET World and I would appreciate the more detailed answers. Thanks everyone. :)
I don't know about best practices, but, I'm using phantomJS with no problems with the following code.
public ActionResult DownloadStatement(int id)
{
string serverPath = HttpContext.Server.MapPath("~/Phantomjs/");
string filename = DateTime.Now.ToString("ddMMyyyy_hhmmss") + ".pdf";
new Thread(new ParameterizedThreadStart(x =>
{
ExecuteCommand("cd " + serverPath + #" & phantomjs rasterize.js http://localhost:8080/filetopdf/" + id.ToString() + " " + filename + #" ""A4""");
})).Start();
var filePath = Path.Combine(HttpContext.Server.MapPath("~/Phantomjs/"), filename);
var stream = new MemoryStream();
byte[] bytes = DoWhile(filePath);
return File(bytes, "application/pdf", filename);
}
private void ExecuteCommand(string Command)
{
try
{
ProcessStartInfo ProcessInfo;
Process Process;
ProcessInfo = new ProcessStartInfo("cmd.exe", "/K " + Command);
ProcessInfo.CreateNoWindow = true;
ProcessInfo.UseShellExecute = false;
Process = Process.Start(ProcessInfo);
}
catch { }
}
public ViewResult FileToPDF(int id)
{
var viewModel = file.Get(id);
return View(viewModel);
}
private byte[] DoWhile(string filePath)
{
byte[] bytes = new byte[0];
bool fail = true;
while (fail)
{
try
{
using (FileStream file = new FileStream(filePath, FileMode.Open, FileAccess.Read))
{
bytes = new byte[file.Length];
file.Read(bytes, 0, (int)file.Length);
}
fail = false;
}
catch
{
Thread.Sleep(1000);
}
}
System.IO.File.Delete(filePath);
return bytes;
}
Here is the action flow:
The user clicks on a link to DownloadStatement Action. Inside there, a new Thread is created to call the ExecuteCommand method.
The ExecuteCommand method is responsible to call phantomJS. The string passed as an argument do the following.
Go to the location where the phantomJS app is and, after that, call rasterize.js with an URL, the filename to be created and a print format. (More about rasterize here).
In my case, what I really want to print is the content delivered by the action filetoupload. It's a simple action that returns a simple view. PhantomJS will call the URL passed as parameter and do all the magic.
While phantomJS is still creating the file, (I guess) I can not return the request made by the client. And that is why I used the DoWhile method. It will hold the request until the file is created by phantomJS and loaded by the app to the request.
If you're open to using NReco.PhantomJS, which provides a .NET wrapper for PhantomJS, you can do this very succinctly.
public async Task<ActionResult> DownloadPdf() {
var phantomJS = new PhantomJS();
try {
var temp = Path.Combine(Path.GetTempPath(),
Path.ChangeExtension(Path.GetRandomFileName(), "pdf")); //must end in .pdf
try {
await phantomJS.RunAsync(HttpContext.Server.MapPath("~/Scripts/rasterize.js"),
new[] { "https://www.google.com", temp });
return File(System.IO.File.ReadAllBytes(temp), "application/pdf");
}
finally {
System.IO.File.Delete(temp);
}
}
finally {
phantomJS.Abort();
}
}
Here's some very basic code to generate a PDF using Phantom.JS but you can find more information here: https://buttercms.com/blog/generating-pdfs-with-node
var webPage = require('webpage');
var page = webPage.create();
page.viewportSize = { width: 1920, height: 1080 };
page.open("http://www.google.com", function start(status) {
page.render('google_home.pdf, {format: 'pdf', quality: '100'});
phantom.exit();
});

Workflow application.PersistableIdle event not firing

Hi I am new to Windows Workflow. This may be very easy, but I am stuck on this from long.
I have a state machine workflow, in which i have a workflow host class.
Persistence is not working in this code. While debugging pointer never goes to application.persistableIdle event.
I use custom input argument, for which I have set as Serializable.
below is my code of the host class:
static InstanceStore instanceStore;
static AutoResetEvent instanceUnloaded = new AutoResetEvent(false);
static Activity activity = new Activity1();
static Guid id = new Guid();
static int intContractHeaderKey;
static Contract contract = new Contract();
public ContractActivityHost(Guid wfid, Int32 contractHeaderID)
{
SetupInstanceStore();
StartAndUnloadInstance(contractHeaderID);
if (intContractHeaderKey > 0)
{
LoadAndCompleteInstance(id, intContractHeaderKey);
}
}
static void StartAndUnloadInstance(Int32 contractHeaderID)
{
contract = new Contract();
//var objContract = new object();
var input = new Dictionary<string, object>
{
{"TheContract", contract}
};
input.Add("ContractHeaderKey", contractHeaderID);
WorkflowApplication application = new WorkflowApplication(activity, input);
application.InstanceStore = instanceStore;
//returning IdleAction.Unload instructs the WorkflowApplication to persists application state and remove it from memory
application.PersistableIdle = (e) =>
{
return PersistableIdleAction.Unload;
};
application.Unloaded = (e) =>
{
instanceUnloaded.Set();
};
//application.Idle = (e) =>
// {
// //application.Unload();
// instanceUnloaded.Set();
// };
//This call is not required
//Calling persist here captures the application durably before it has been started
application.Persist();
id = application.Id;
application.Run();
instanceUnloaded.WaitOne();
//application.Unload();
//contract = (Contract)objContract;
intContractHeaderKey = contract.ContractID;
}
static void LoadAndCompleteInstance(Guid wfid, Int32 contractHeaderID)
{
//string input = Console.ReadLine();
while (!contract.ContractWFPause)
{
contract.FireContract(contract.ContractID);
WorkflowApplication application = new WorkflowApplication(activity);
application.InstanceStore = instanceStore;
application.Completed = (workflowApplicationCompletedEventArgs) =>
{
//Console.WriteLine("\nWorkflowApplication has Completed in the {0} state.", workflowApplicationCompletedEventArgs.CompletionState);
strWFStatus = "Completed";
};
application.Unloaded = (workflowApplicationEventArgs) =>
{
//Console.WriteLine("WorkflowApplication has Unloaded\n");
strWFStatus = "Unloaded";
instanceUnloaded.Set();
};
application.Load(wfid);
instanceUnloaded.WaitOne();
}
}
private static void SetupInstanceStore()
{
instanceStore =
new SqlWorkflowInstanceStore(#"Data Source=.;Initial Catalog=WorkflowInstanceStore;Integrated Security=True;");
InstanceHandle handle = instanceStore.CreateInstanceHandle();
InstanceView view = instanceStore.Execute(handle, new CreateWorkflowOwnerCommand(), TimeSpan.FromSeconds(10));
handle.Free();
instanceStore.DefaultInstanceOwner = view.InstanceOwner;
}
I have been trying to resolve this from long time, but not sure where I am missing anything. I have gone through couple of sample applications and changed my code to match the flow and logic, but still it does not work.
After application.persist, record is inserted in [System.Activities.DurableInstancing].[InstancesTable] view.
But debug pointer does not move beyond instanceUnloaded.WaitOne();
it actually goes to idle state. if I uncomment application.idle event, it goes in that event code.
Any help to resolve this would be great.
Thanks.
Please check If you have added the below details
instanceStore = new SqlWorkflowInstanceStore(ConfigurationManager.ConnectionStrings["WFPersistenceDb"].ConnectionString);
StateMachineStateTracker.Promote(this.instanceStore);

Content service returns old content for some time

I'm using following snippet for saving content:
private void writeToFile(NodeRef nodeRef, String content) throws IOException {
ContentWriter writer = contentService.getWriter(nodeRef, ContentModel.PROP_CONTENT, true);
InputStream contentStream = new ByteArrayInputStream(content.getBytes(encoding));
writer.setMimetype(mimeType);
writer.setEncoding(encoding);
writer.putContent(contentStream);
Map<QName, Serializable> repoProps = nodeService.getProperties(nodeRef);
ContentData contentData = (ContentData) repoProps.get(ContentModel.PROP_CONTENT);
if(contentData == null)
contentData = writer.getContentData();
contentData = ContentData.setEncoding(contentData, encoding);
contentData = ContentData.setMimetype(contentData, mimeType);
repoProps.put(ContentModel.PROP_CONTENT, contentData);
contentStream.close();
nodeService.setProperties(nodeRef, repoProps);
}
When I read content written this way within short period of time (depends on server load) in other place, old content is returned. So it looks like that maybe indexing is in progress, so before final commit old content is returned, is that possible? If so, is it possible to override this behavior and access newest possible content? Via contentUrl?
To avoid this behavior I'm using thread for each read request, which sleeps for some time at the beginning, but I really dislike this "solution".
Edit: I built from newest SVN source, running on Tomcat 6.0.35 on Linux (CentOS and Ubuntu); system load - i mean hundreds of files changing every few seconds.
Edit: reading looks like this:
private byte[] readFileContent(NodeRef nodeRef) throws IOException {
ContentReader reader = contentService.getReader(nodeRef, ContentModel.PROP_CONTENT);
if(reader == null)
return null;
InputStream originalInputStream = reader.getContentInputStream();
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
final int BUF_SIZE = 1 << 8; // 1KiB buffer
byte[] buffer = new byte[BUF_SIZE];
int bytesRead = -1;
while ((bytesRead = originalInputStream.read(buffer)) > -1) {
outputStream.write(buffer, 0, bytesRead);
}
originalInputStream.close();
return outputStream.toByteArray();
}
Ok, solved with simplier saving like this:
ContentWriter writer = contentService.getWriter(nodeRef, ContentModel.PROP_CONTENT, true);
InputStream contentStream = new ByteArrayInputStream(content.getBytes(encoding));
writer.setMimetype(mimeType);
writer.setEncoding(encoding);
writer.putContent(contentStream);
contentStream.close();
Previous saving was at place because of some content encoding problems, so testing shows if this works.

Resources