Sensenet: upload files through sensenet client API for version 6.5 is not working properly - sensenet

I have installed SenseNet version 6.5 (Code from codeplex). Wanted to upload the files in content repositry using Sensenet Client API, unfortunately it is not working with bulk upload.
string [] fileEntries = Directory.GetFiles(#"C:\Users\conyna\Downloads\Chirag");
foreach (string fileName in fileEntries)
{
using (Stream fs = File.OpenRead(fileName))
{
string fn = Path.GetFileName(fileName);
Task<SenseNet.Client.Content> x = SenseNet.Client.Content.UploadAsync("/Root/Sites/Default_Site/workspaces/(apps)/DocumentLibrary", fn, fs);
}
}

There are two problems with the code above:
you have to 'await' for async methods. Currently you start the task with the UploadAsync method, but you do not wait for it to finish, which casuses problems, because the file stream closes immediately after starting the upload task. Please upload files in an async way (of course you'll have to make your caller method async too, but that is the point of using an async api):
await Content.UploadAsync(...)
You may also consider using the Importer class in the client, it is able to import full directory structures.
You are trying to upload into an (apps) folder, which is not a correct target, that was designed to contain applications (mostly pages). It would be better if you uploaded into a document library in a workspace, for example:
/Root/Sites/Default_Site/workspaces/Document/SampleWorkspace/DocumentLibrary

We created a small application with SN ClientLibrary. I think, you can use this application/information/code.
This application can upload entire folders via Client Libray. Please check it out my Github repository: https://github.com/marosvolgyiz/SNClientLibraryUploader
There is relevant upload method:
public async Task Upload()
{
try
{
Console.WriteLine("Initilization...");
ClientContext.Initialize(new[] { sctx });
Console.WriteLine("Upload Started");
//Is Parent exists
var content = await Content.LoadAsync(Target);
if (content != null)
{
//Uploading files
var tasks = new List<Task>();
foreach (var file in Files)
{
string fileTargetFolder = Target + file.DirectoryName.Replace(Source, "").Replace(BaseDirectory, "").Replace("\\", "/");
var fileTargetContentFolder = await Content.LoadAsync(fileTargetFolder);
if (fileTargetContentFolder == null)
{
if (CreateFolderPath(Target, file.DirectoryName.Replace(Source, "")))
{
fileTargetContentFolder = await Content.LoadAsync(fileTargetFolder);
Console.WriteLine("#Upload file: " + file.FullName);
tasks.Add(Content.UploadAsync(fileTargetContentFolder.Id, file.Name, file.OpenRead()));
LoggerClass.LogToCSV("File uploaded", file.Name);
}
else
{
LoggerClass.LogToCSV("File target folder does not exist or you do not have enough permission to see! File can not be uploaded. ", file.Name);
}
}
else
{
Console.WriteLine("#Upload file: " + file.FullName);
tasks.Add(Content.UploadAsync(fileTargetContentFolder.Id, file.Name, file.OpenRead()));
LoggerClass.LogToCSV("File uploaded", file.Name);
}
}
await Task.WhenAll(tasks);
}
else
{
Console.WriteLine("Target does not exist or you do not have enough permission to see!");
LoggerClass.LogToCSV("Target does not exist or you do not have enough permission to see!");
}
Console.WriteLine("Upload finished.");
}
catch (Exception ex)
{
LoggerClass.LogToCSV(ex.Message);
}
}
I hope my answer is helpful to you.
Br,
maros

Related

How to save zip compressed folder to disk asp.net core 3.0

I want to upload and save a zipped folder to a path on my disk drive using .net core 3.0 but the zipped folder is saving as 0bytes
[HttpPost]
[ValidateAntiForgeryToken()]
[RequestFormLimits(MultipartBodyLengthLimit = 20971520)]//max size should be 20MB
public IActionResult AddFile(List<IFormFile> files)
{
IActionResult ar = null;
try
{
if (id != 0)
{
foreach(var singlefile in files)
{
var ext = Path.GetExtension(singlefile.FileName).ToLowerInvariant();
//begin saving procedure
if(singlefile.Length > 0 && singlefile.Length <= Convert.ToInt32(_config.Value.FileSizeLimit))
{
var filepath = Path.Combine(_config.Value.StoredFilesPath, Path.GetRandomFileName().Split('.')[0] + ext);
using(var stream = System.IO.File.Create(filepath))
{
singlefile.CopyToAsync(stream);
}
}
}
}
catch (Exception e)
{
_log.Error(e);
}
return ar;
}
Please What am i missing out? I can save files with other extensions using this same piece of code, it saves and i can view properly but only .zip files saves as 0bytes
You didn't wait for the copy task to complete. Try change the method to an async action:
public async Task<IActionResult> AddFile(List<IFormFile> files)
{
...
using(var stream = System.IO.File.Create(filepath))
{
await singlefile.CopyToAsync(stream); // await here, otherwise the stream is disposed quickly
}
...
}

Need a web API action method to implement removeUrl of kendo angular upload component

I need a full working example for implementing the remove functionality in telerik kendo angular with Angular 8 and a backend web API in ASP.net core 2.2
In kendo Angular I'm trying to implement the functionality of upload files and removing it when user clicks the x small buttons
I've already implemented the upload so perfectly but when providing the removeUrl it gives error 404 or 415
The other strange thing is when I provide the same url for the upload and download it binds and code could go well but i need a separate action for the remove functionality
[HttpPost("upload"), DisableRequestSizeLimit]
public async Task<IActionResult> Post(IFormFileCollection files)
{
long size = files.Sum(f => f.Length);
//var reqFiles = Request.Form.Files;
var uploads = Path.Combine(_hostingEnvironment.WebRootPath, "uploads");
if (!Directory.Exists(uploads))
{
Directory.CreateDirectory(uploads);
}
List<string> paths = new List<string>();
foreach (var file in files)
{
if (file.Length > 0)
{
string fileName = Guid.NewGuid() + Path.GetExtension(file.FileName);
var filePath = Path.Combine(uploads, fileName);
using (var fileStream = new FileStream(filePath, FileMode.Create))
{
await file.CopyToAsync(fileStream);
}
paths.Add(filePath);
}
}
// process uploaded files
// Don't rely on or trust the FileName property without validation.
return Ok(new { count = files.Count, size, paths });
}
and for delete
[HttpPost]
private IActionResult Delete(IList<string> files)
{
// var reqFiles = Request.Form.Files;
var uploads = Path.Combine(_hostingEnvironment.WebRootPath, "uploads");
foreach (var item in files)
{
var filePath = Path.Combine(uploads, item);
System.IO.File.Delete(filePath);
}
return Ok(new { files });
}
Error 404 is raised when trying to name the action in web api and provide this name in the url (although the same thing is working when uploadling) and 415 is being raised when using post request without naming the action in the back end

Files uploaded but not appearing on server

I use the code stated here to upload files through a webapi http://bartwullems.blogspot.pe/2013/03/web-api-file-upload-set-filename.html. I also made the following api to list all the files I have :
[HttpPost]
[Route("sharepoint/imageBrowser/listFiles")]
[SharePointContextFilter]
public async Task<HttpResponseMessage> Read()
{
string pathImages = HttpContext.Current.Server.MapPath("~/Content/images");
DirectoryInfo d = new DirectoryInfo(pathImages);//Assuming Test is your Folder
FileInfo[] Files = d.GetFiles(); //Getting Text files
List<object> lst = new List<object>();
foreach (FileInfo f in Files)
{
lst.Add(new
{
name = f.Name,
type = "f",
size = f.Length
});
}
return Request.CreateResponse(HttpStatusCode.OK, lst);
}
When calling this api, all the files uploaded are listed. But when I go to azure I dont see any of them (Content.png is a file I manually uploaded to azure)
Why are the files listed if they dont appear on azure.
According to your description, I suggest you could firstly use azure kudu console to locate the right folder in the azure web portal to see the image file.
Open kudu console:
In the kudu click the debug console and locate the site\wwwroot\yourfilefolder
If you find your file is still doesn't upload successfully, I guess there maybe something wrong with your upload codes. I suggest you could try below codes.
Notice: You need add image folder in the wwwort folder.
{
public class UploadingController : ApiController
{
public async Task<HttpResponseMessage> PostFile()
{
// Check if the request contains multipart/form-data.
if (!Request.Content.IsMimeMultipartContent())
{
throw new HttpResponseException(HttpStatusCode.UnsupportedMediaType);
}
string root = Environment.GetEnvironmentVariable("HOME").ToString() + "\\site\\wwwroot\\images";
//string root = HttpContext.Current.Server.MapPath("~/images");
var provider = new FilenameMultipartFormDataStreamProvider(root);
try
{
StringBuilder sb = new StringBuilder(); // Holds the response body
// Read the form data and return an async task.
await Request.Content.ReadAsMultipartAsync(provider);
// This illustrates how to get the form data.
foreach (var key in provider.FormData.AllKeys)
{
foreach (var val in provider.FormData.GetValues(key))
{
sb.Append(string.Format("{0}: {1}\n", key, val));
}
}
// This illustrates how to get the file names for uploaded files.
foreach (var file in provider.FileData)
{
FileInfo fileInfo = new FileInfo(file.LocalFileName);
sb.Append(string.Format("Uploaded file: {0} ({1} bytes)\n", fileInfo.Name, fileInfo.Length));
}
return new HttpResponseMessage()
{
Content = new StringContent(sb.ToString())
};
}
catch (System.Exception e)
{
return Request.CreateErrorResponse(HttpStatusCode.InternalServerError, e);
}
}
}
public class FilenameMultipartFormDataStreamProvider : MultipartFormDataStreamProvider
{
public FilenameMultipartFormDataStreamProvider(string path) : base(path)
{
}
public override string GetLocalFileName(System.Net.Http.Headers.HttpContentHeaders headers)
{
var name = !string.IsNullOrWhiteSpace(headers.ContentDisposition.FileName) ? headers.ContentDisposition.FileName : Guid.NewGuid().ToString();
return name.Replace("\"", string.Empty);
}
}
}
Result:

asp.net web api file upload without saving

Ok, so I am writing a service to recieve file uploads from an iPhone application through phonegap. They send me a file and I am trying to grab the actual file without saving it to any type of file system. Currently this is what I have
[HttpPost]
public string processRequest()
{
string ext = "Entered";
Request.Content.ReadAsMultipartAsync<MultipartMemoryStreamProvider>(new MultipartMemoryStreamProvider()).ContinueWith((tsk) =>
{
ext = "Request";
MultipartMemoryStreamProvider prvdr = tsk.Result;
foreach (HttpContent ctnt in prvdr.Contents)
{
ext = "Foreach";
// You would get hold of the inner memory stream here
Stream stream = ctnt.ReadAsStreamAsync().Result;
if (stream == null)
{
ext = "Null Stream";
}
Image img = Image.FromStream(stream);
if (ImageFormat.Jpeg.Equals(img.RawFormat))
{
ext = "jpeg";
}
else if (ImageFormat.Png.Equals(img.RawFormat))
{
ext = "Png";
}
else if (ImageFormat.Gif.Equals(img.RawFormat))
{
ext = "Gif";
}
// do something witht his stream now
}
});
return ext;
}
I have put various responses in there so I can see where the function is getting to. Right now it always returns "Entered" which means its not even reading the content of the request, the end game is for me to grab the file object, convert it into an image and then to base 64. Any direction would be appreciated. Remember I want to do this without any file system so no solutions that involve mapping a path to a server folder.
Ok so a little update, I have edited my code according to my first response and at least it attempts to execute now but it just gets infinitely stuck inside the code. This happens during the ReadAsMultipartAsync function
[HttpPost]
public string processRequest()
{
string ext = "Entered";
Request.Content.ReadAsMultipartAsync(new MultipartMemoryStreamProvider()).ContinueWith((tsk) =>
{
ext = "Request";
MultipartMemoryStreamProvider prvdr = tsk.Result;
foreach (HttpContent ctnt in prvdr.Contents)
{
ext = "Foreach";
// You would get hold of the inner memory stream here
Stream stream = ctnt.ReadAsStreamAsync().Result;
if (stream == null)
{
ext = "Null Stream";
}
Image img = Image.FromStream(stream);
if (ImageFormat.Jpeg.Equals(img.RawFormat))
{
ext = "jpeg";
}
else if (ImageFormat.Png.Equals(img.RawFormat))
{
ext = "Png";
}
else if (ImageFormat.Gif.Equals(img.RawFormat))
{
ext = "Gif";
}
// do something witht his stream now
}
}).Wait();
return ext;
}
The block inside ContinueWith also runs asynchronously (if you look at the signature for ContinueWith, you'll see that it returns a Task as well). So, with the above code, essentially you're returning before any of that has a chance to execute.
Try doing:
Request.Content.ReadAsMultipartAsync().ContinueWith(...).Wait();
Also, not sure you need to go to the trouble of doing Request.Content.ReadAsMultipartAsync<MultipartMemoryStreamProvider>(new MultipartMemoryStreamProvider()); I believe Request.Content.ReadAsMultipartAsync() should suffice.
Hope that helps!

Cannot Open Files in WinRT Unit Testing

I am writing a unit test to validate the serialization of objects and I am able to successfully save the file without any issue. I can even browse the file and validate the contents are correct. However, when I attempt to open the file for reading I always receive an UnauthorizedAccess exception.
Here is the code used to save the item:
public static async Task SaveItem<T>(string folderName, T item)
where T : BaseBusinessItem
{
if (string.IsNullOrEmpty(folderName))
{
throw new ArgumentNullException("folderName");
}
if (item == null)
{
throw new ArgumentNullException("item");
}
try
{
var folder = await ApplicationData.Current.LocalFolder
.CreateFolderAsync(folderName, CreationCollisionOption.OpenIfExists);
var file =
await
folder.CreateFileAsync(item.UniqueID.GetHashCode().ToString(), CreationCollisionOption.ReplaceExisting);
var stream = await file.OpenAsync(FileAccessMode.ReadWrite);
using (var outStream = stream.GetOutputStreamAt(0))
{
var serializer = new DataContractJsonSerializer(typeof(T));
serializer.WriteObject(outStream.AsStreamForWrite(), item);
await outStream.FlushAsync();
}
}
catch (Exception ex)
{
Debug.WriteLine(ex.ToString());
}
}
Here is the code used to restore the item:
public static async Task<T> RestoreItem<T>(string folderName, string hashCode)
where T : BaseBusinessItem, new()
{
if (string.IsNullOrEmpty(folderName))
{
throw new ArgumentNullException("folderName");
}
if (string.IsNullOrEmpty(hashCode))
{
throw new ArgumentNullException("hashCode");
}
var folder = await ApplicationData.Current.LocalFolder.GetFolderAsync(folderName);
var file = await folder.GetFileAsync(hashCode);
var inStream = await file.OpenSequentialReadAsync();
var serializer = new DataContractJsonSerializer(typeof(T));
var retVal = (T)serializer.ReadObject(inStream.AsStreamForRead());
return retVal;
}
And the unit test:
[TestMethod]
public async Task TestFileSaveLoad()
{
await _ds.SaveItem("TestFolder");
Guid ID = _item.UniqueID;
_ds = await ItemDataSource.LoadItem("TestFolder", ID.GetHashCode().ToString());
}
Any ideas or troubleshooting steps I might be missing. The unit test app manifest includes the following capabilities: Document Library, Internet (Client). The following declarations are in place: File Open Picker, File Save Picker and File Type Associations.
Thanks!
This code snippet helped me accomplish my goal. Hope this is helpful for someone else:
http://codepaste.net/gtu5mq