How to download file from FileCabinet in NetSuite using C# - c#

I need to download text file from FileCabinet in NetSuite. I am able to search for all files in a folder and get back the file size, name and URL. But when I check the 'content' property, it is NULL. How can I download the file locally?
I tried using the URL to download the file using WebClient, but it returns 403 which makes sense.
var result = Client.Service.search(fileSearch);
var recordList = (Record[])result.recordList;
if (recordList != null && recordList.Length != 0)
{
foreach (var item in recordList)
{
var file = (com.netsuite.webservices.File)item;
int fileSize = (int)file.fileSize; // Returns the correct file size
byte[] fileContent = file.content; // NULL reference ??
Console.WriteLine(file.url + " ==== " + file.name );
// How to download the File from the url above??
// Can't do this, 403 error, below client dont use the same security context
//using (var client = new WebClient())
//{
// client.UseDefaultCredentials = false;
// client.DownloadFile(baseUrl + file.url, file.name);
//}
}
}
I expected 'content' to contain the file content.

When you execute a search, the search results do not include the contents of the file, but you DO have the file id. Below is an extension method on the NetSuite service to get a file by it's id:
public static NetSuite.File GetFileById(this NetSuiteService ns, int fileId)
{
var file = new NetSuite.File();
var response = ns.get(new RecordRef()
{
type = RecordType.file,
internalId = fileId.ToString(),
typeSpecified = true
});
if (response.status.isSuccess)
{
file = response.record as File;
}
return file;
}
var f = ns.GetFileById(3946);
var path = Path.Combine(Directory.GetCurrentDirectory(), f.name);
var contents = f.content;
System.IO.File.WriteAllBytes(path, contents);
Console.WriteLine($"Downloaded {f.name}");

Related

Action Result File - Filename when downloading is wrong in some cases

So this is the Code that returns the file. It is in a Method named GetMainReport.
var mBytes = MergePDF(formLanguage, mergedForms);
if (mBytes != null)
{
var cd = new System.Net.Mime.ContentDisposition
{
FileName = formLanguage.FileName,
Inline = formLanguage.FileExtension == FileExtension.PDF
};
Response.Headers.Add("content-disposition", cd.ToString());
AddDownloadedForm(formLanguage.Id);
return File(mBytes, type);
}
My Problem now is that if i go via this url:
http://localhost:8090/Library/105020.pdf
The filename when downloaded is 105020.pdf
if i use this one
http://localhost:8090/FormSearch/FormSearch/getMainReport?FormNumber=105020%20%20de
The filename is GetMainReport.pdf
any ideas why?
try this settings for ContentDisposition:
var cd = new System.Net.Mime.ContentDisposition
{
FileName = formLanguage.FileName,
DispositionType = DispositionTypeNames.Attachment,
Inline = formLanguage.FileExtension == FileExtension.PDF
};

How to display image angular from .net core API and database

I would like to display a picture whose path it stores in the database
this is how it transfers the image file to the database.
public string UploadImage(IFormFile file)
{
if (file == null) throw new Exception("Pusty plik");
if (file.Length == 0)
{
throw new Exception("Pusty plik");
}
if (!ACCEPTED_FILE_TYPES.Any(s => s == Path.GetExtension(file.FileName).ToLower())) throw new Exception("Zły typ pliku");
if (string.IsNullOrWhiteSpace(host.WebRootPath))
{
host.WebRootPath = Path.Combine(Directory.GetCurrentDirectory(), "wwwroot");
}
var uploadFilesPath = Path.Combine(host.WebRootPath, "images");
if (!Directory.Exists(uploadFilesPath))
Directory.CreateDirectory(uploadFilesPath);
var fileName = Guid.NewGuid().ToString() + Path.GetExtension(file.FileName);
var filePath = Path.Combine(uploadFilesPath, fileName);
using (var stream = new FileStream(filePath, FileMode.Create))
{
file.CopyToAsync(stream);
}
var path = Path.Combine(Directory.GetCurrentDirectory(), #"/wwwroot/images/", fileName);
return path;
}
here stores files:
https://zapodaj.net/a8829a7a3a90b.png.html
In your sample code I do not see path returning from database.
Also from security point of view it would be bad practice to return /wwwroot/images/ in response. You can create a folder on shared location and return shared location path.
Seems you question and same code isn't aligning.

Can't upload file to Document Library using CSOM

I am trying to upload multiple file to a Document Library and also update its coloumn values.
List(Doc Lib) already exists but I am stuck with uploadinf the file
I've tried these methods
using lists.asmx
NetworkCredential credentials = new NetworkCredential("user", "Pass", "domain");
#region ListWebService
ListService.Lists listService = new ListService.Lists();
listService.Credentials = credentials;
List list = cc.Web.Lists.GetByTitle(library);
listService.Url = cc.Url + "/_vti_bin/lists.asmx";
try
{
FileStream fStream = System.IO.File.OpenRead(filePath);
string fName = fStream.Name.Substring(3);
byte[] contents = new byte[fStream.Length];
fStream.Read(contents, 0, (int)fStream.Length);
fStream.Close();
string attach = listService.AddAttachment(library, itemId.ToString(), Path.GetFileName(filePath), contents);
}
#endregion
catch (System.Web.Services.Protocols.SoapException ex)
{
CSVWriter("Message:\n" + ex.Message + "\nDetail:\n" +
ex.Detail.InnerText + "\nStackTrace:\n" + ex.StackTrace, LogReport);
}
It gives a error ServerException :To add an item to a document library, use SPFileCollection.Add() on AddAttachment()
Using
List lib = cc.Web.Lists.GetByTitle("TestLib");
FileCreationInformation fileInfo = new FileCreationInformation();
fileInfo.Content = System.IO.File.ReadAllBytes("C:\\Users\\AJohn\\Desktop\\sample.docx");
fileInfo.Url = "https://serverm/sites/Testing1/TestLib/sample.docx";
fileInfo.Overwrite = true;
Microsoft.SharePoint.Client.File upFile = lib.RootFolder.Files.Add(fileInfo);
cc.Load(upFile);
cc.ExecuteQuery();
I was able to upload once using this method, but now I am getting ServerException :To add an item to a document library, use SPFileCollection.Add() on cc.ExecuteQuery()
But if at all this method works, what I want is that I should update the coloumn values related to this file. In first method I get item.ID so from there I can update the Coloumn Values
Regarding the second method, the following example demonstrates how to upload a file into Documents library and set it's properties (e.g. Category text field)
using (var ctx = new ClientContext(webUri))
{
var targetList = ctx.Web.Lists.GetByTitle("Documents");
var fileInfo = new FileCreationInformation
{
Url = System.IO.Path.GetFileName(sourcePath),
Content = System.IO.File.ReadAllBytes(sourcePath),
Overwrite = true
};
var file = targetList.RootFolder.Files.Add(fileInfo);
var item = file.ListItemAllFields;
item["Category"] = "User Guide";
item.Update();
ctx.ExecuteQuery();
}

Sharepoint uploaded file name was changed by server event. How to retrieve it?

I'm uploading file to Sharepoint server using this code:
ClientOM.File uploadFile = null;
try {
string fileRef = serverRelativeURL + msg.Message.FileName;
FileCreationInformation fileCreationInformation = new FileCreationInformation() {
Content = msg.Content,
Url = fileRef,
Overwrite = true
};
uploadFile = _currentList.RootFolder.Files.Add(fileCreationInformation);
_currentContext.ExecuteQuery();
And file uploaded. But on server we have event that adds some random string to the file title. So fileRef is not relevant after upload.
And we need to set the Author of the file. For this we have to retrieve file and update this propery. I do it with this sample:
string fileName = serverRelativeURL + msg.Message.FileName;
uploadFile = _currentContext.Web.GetFileByServerRelativeUrl(fileName);
_currentContext.Load(uploadFile);
uploadFile.ListItemAllFields["Author"] = _currentUser;
uploadFile.ListItemAllFields["Editor"] = _currentUser;
uploadFile.ListItemAllFields.Update();
_currentContext.ExecuteQuery();
And on ExecuteQuery() I get an Exception "File not found". But if I copy path from Sharepoint (with that random string) everything works Ok.
So the question is: Is there other way to retrieve file? By id for example? because when we uploading file, instance "uploadFile" does not have much of useful information.
Method 1:
Keep track of the filename, and then use this code to retrieve it directly.
public FileInformation GetFileFromAttachment(int itemId, string filename)
{
FileInformation file = null;
//continue here
if (new FileInfo(filename).Name != null)
{
CSOMUtils.ExecuteInNewContext(QueryConfig.siteUrl, delegate(ClientContext clientContext)
{
clientContext.Credentials = QueryConfig.credentials;
clientContext.Load(clientContext.Web, l => l.ServerRelativeUrl);
clientContext.ExecuteQuery();
List oList = clientContext.Web.Lists.GetByTitle(ListName);
clientContext.ExecuteQuery();
string url = string.Format("{0}/Lists/{1}/Attachments/{2}/{3}",
clientContext.Web.ServerRelativeUrl,
ListName,
itemId,
filename);
var f = clientContext.Web.GetFileByServerRelativeUrl(url);
clientContext.Load(f);
clientContext.ExecuteQuery();
file = File.OpenBinaryDirect(clientContext, f.ServerRelativeUrl);
});
}
return file;
}
Method 2:
You can use ServerRelativeUrl to get the folder containing all the attachments.
https://msdn.microsoft.com/library/office/microsoft.sharepoint.client.folder.serverrelativeurl.aspx
https://sharepoint.stackexchange.com/questions/132008/reliably-get-attachments-for-list-item

How to copy file from one library to another library using CSOM?

I need to copy a particular file from one library to another library.
At first, need to check if file is existing in that library.
If Existing, then need to overwrite file content and new sharepoint version should be updated for that document.
I need to do this using c# CSOM and sharepoint version is 2013.
Thanks in advance :)
public static void CopyDocuments(string srcUrl, string destUrl, string srcLibrary, string destLibrary, Login _login)
{
// set up the src client
SP.ClientContext srcContext = new SP.ClientContext(srcUrl);
srcContext.AuthenticationMode = SP.ClientAuthenticationMode.FormsAuthentication;
srcContext.FormsAuthenticationLoginInfo = new SP.FormsAuthenticationLoginInfo(_login.UserName, _login.Password);
// set up the destination context (in your case there is no needs to create a new context, because it would be the same library!!!!)
SP.ClientContext destContext = new SP.ClientContext(destUrl);
destContext.AuthenticationMode = SP.ClientAuthenticationMode.FormsAuthentication;
destContext.FormsAuthenticationLoginInfo = new SP.FormsAuthenticationLoginInfo(_login.UserName, _login.Password);
// get the list and items
SP.Web srcWeb = srcContext.Web;
SP.List srcList = srcWeb.Lists.GetByTitle(srcLibrary);
SP.ListItemCollection col = srcList.GetItems(new SP.CamlQuery());
srcContext.Load(col);
srcContext.ExecuteQuery();
// get the new list
SP.Web destWeb = destContext.Web;
destContext.Load(destWeb);
destContext.ExecuteQuery();
foreach (var doc in col)
{
try
{
if (doc.FileSystemObjectType == SP.FileSystemObjectType.File)
{
// get the file
SP.File f = doc.File;
srcContext.Load(f);
srcContext.ExecuteQuery();
// build new location url
string nLocation = destWeb.ServerRelativeUrl.TrimEnd('/') + "/" + destLibrary.Replace(" ", "") + "/" + f.Name;
// read the file, copy the content to new file at new location
SP.FileInformation fileInfo = SP.File.OpenBinaryDirect(srcContext, f.ServerRelativeUrl);
SP.File.SaveBinaryDirect(destContext, nLocation, fileInfo.Stream, true);
}
if (doc.FileSystemObjectType == SP.FileSystemObjectType.Folder)
{
// load the folder
srcContext.Load(doc);
srcContext.ExecuteQuery();
// get the folder data, get the file collection in the folder
SP.Folder folder = srcWeb.GetFolderByServerRelativeUrl(doc.FieldValues["FileRef"].ToString());
SP.FileCollection fileCol = folder.Files;
// load everyting so we can access it
srcContext.Load(folder);
srcContext.Load(fileCol);
srcContext.ExecuteQuery();
foreach (SP.File f in fileCol)
{
// load the file
srcContext.Load(f);
srcContext.ExecuteQuery();
string[] parts = null;
string id = null;
if (srcLibrary == "My Files")
{
// these are doc sets
parts = f.ServerRelativeUrl.Split('/');
id = parts[parts.Length - 2];
}
else
{
id = folder.Name;
}
// build new location url
string nLocation = destWeb.ServerRelativeUrl.TrimEnd('/') + "/" + destLibrary.Replace(" ", "") + "/" + id + "/" + f.Name;
// read the file, copy the content to new file at new location
SP.FileInformation fileInfo = SP.File.OpenBinaryDirect(srcContext, f.ServerRelativeUrl);
SP.File.SaveBinaryDirect(destContext, nLocation, fileInfo.Stream, true);
}
}
}
catch (Exception ex)
{
Log("File Error = " + ex.ToString());
}
}
}
Source: https://sharepoint.stackexchange.com/questions/114033/how-do-i-move-files-from-one-document-library-to-another-using-jsom
I strongly advise against using the approach suggested by Nikerym. You don't want to download the bytes only to upload them unmodified. It's slow and error-prone. Instead, use the built-in method provided by the CSOM API.
https://learn.microsoft.com/en-us/previous-versions/office/sharepoint-server/mt162553(v=office.15)?redirectedfrom=MSDN
var srcPath = "https://YOUR.sharepoint.com/sites/xxx/SitePages/Page.aspx";
var destPath = $"https://YOUR.sharepoint.com/sites/xxx/SitePages/CopiedPage.aspx";
MoveCopyUtil.CopyFileByPath(ctx, ResourcePath.FromDecodedUrl(srcPath), ResourcePath.FromDecodedUrl(destPath), false, new MoveCopyOptions());
ctx.ExecuteQuery();
You can configure the override behavior by adjusting the 4th and 5th arguments of the function signature.
[...]
bool overwrite,
MoveCopyOptions options
https://learn.microsoft.com/en-us/previous-versions/office/sharepoint-server/mt844930(v=office.15)

Categories