I am trying to save an XML file to a non CDN Container from Sydney:
public void Save(XDocument document)
{
using (MemoryStream ms = new MemoryStream())
{
document.Save(ms);
ms.Position = 0;
RackspaceCloudIdentity identity = new RackspaceCloudIdentity { Username = "username", APIKey = "xxxxxxxxxxx", CloudInstance = CloudInstance.Default };
CloudFilesProvider provider = new CloudFilesProvider(identity);
provider.CreateObject("XMLFiles", ms, "xmlFile1.xml", region: "syd");
}
}
For a 1MB file, it takes about 50 seconds to upload (very long).
And, trying to download the file back, returns an empty result:
public void Read()
{
RackspaceCloudIdentity identity = new RackspaceCloudIdentity { Username = "username", APIKey = "xxxxxxxxxxx", CloudInstance = CloudInstance.Default };
CloudFilesProvider provider = new CloudFilesProvider(identity);
using (MemoryStream ms = new MemoryStream())
{
provider.GetObject("XMLFiles", "xmlFile1.xml", ms, region: "syd");
// ms.Length is 0
}
}
I am doing something wrong?
Ugh. I introduced this bug in commit 799f37c (first released in v1.1.3.0). I'm looking into the best workaround right now.
Edit: There is no workaround, but I filed issue #116 for the issue, and after the pull request for it is merged, we'll release version 1.1.3.1 of the library to correct the problem.
Are you able to access your control panel at mycloud.rackspace.com?
I used my control panel to upload an XML file, then used your code, above, to download the XML file. It worked fine.
I'm going now use the upload code you posted.
Just wanted you to know I'm looking into this.
Related
I am developing a Bot application using MS bot framework V4. I want to send Excel file (.xlsx) from Bot to the user, it is a template which user later fills in and send back to Bot. But with the following code, I can see the file in the chat window but user is not able to download the file. How can I achieve this functionality where user can download it.
Note: Please see the ELSE part below where user is supposed to download the Excel template.
private async Task<DialogTurnResult> UploadFileTemplateCheckStepAsync(WaterfallStepContext stepContext, CancellationToken cancellationToken)
{
string choice = ((FoundChoice)stepContext.Result).Value;
if (choice.ToLower().Equals("yes"))
{
stepContext.Values["IsFileTemplate"] = (string)stepContext.Result;
return await stepContext.PromptAsync(nameof(TextPrompt), new PromptOptions
{ Prompt = MessageFactory.Text("Please upload the file.") }, cancellationToken);
}
else
{
//Provide the template.
var ImagePath = Path.Combine(_env.WebRootPath, "TeeUpTemplate.xlsx");
var ImageData = Convert.ToBase64String(File.ReadAllBytes(ImagePath));
Attachment attachment = new Attachment()
{
Name = "TeeUpTemplate.xlsx", ContentType = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
ThumbnailUrl = Path.Combine(_env.WebRootPath, "Excel.png"),
ContentUrl = $"data:application/vnd.ms-excel;base64,{ImageData}"
};
IMessageActivity reply = MessageFactory.Text("Use this template to fill the file.");
reply.Attachments = new List<Attachment>();
reply.Attachments.Add(attachment);
reply.From = stepContext.Context.Activity.From;
await stepContext.Context.SendActivityAsync(reply, cancellationToken);
return await stepContext.PromptAsync(nameof(TextPrompt), new PromptOptions
{ Prompt = MessageFactory.Text("Upload the file") }, cancellationToken);
}
}
Here is the solution which I implemented. If your bot works with attachments then one of the method is One Drive subscription or sharepoint subscription. It is a mandate. I used One Drive subscription. All the attachment first gets uploaded or downloaded to your One Drive Account from where it goes to the bot.
The major drawback for developers is you can not test this in Bot Emulator, it has to be
tested directly in Teams as Content Type = application/vnd.microsoft.teams.file.download.info only has support in Teams.
One more point is you will have to upload Manifest file with file with
"supportsFiles": true,
You may refer this sample for C# to get more insights:
https://github.com/microsoft/BotBuilder-Samples/tree/main/samples/csharp_dotnetcore/56.teams-file-upload
Thank you.
I need to search files by file name and content. Current implementation used Ole DB connection to windows search. But as I understand, Ole db wouldn't be implemented in .net core. I guess that I should use solution like Lucene .So I need advice, how to access windows search from .net-core at least or any ideas how to make that in cross-platform manner without windows search.
You basically have a couple of options. You can get hold of the FTQuery Tool (FTQuery.exe) in Windows 7 SDK and use Process Class in System.Diagnostics to get results by parsing standard output.
Alternatively you can create a separate ASP.NET Web API 2 project to act as a bridge between Windows Search and .NET Core using the following code as an action in your controller.
public async Task<IHttpActionResult> Post()
{
var data = new ArrayList();
var conn = new OleDbConnection("Provider=Search.CollatorDSO;Extended Properties='Application=Windows'");
await conn.OpenAsync();
string sql = await Request.Content.ReadAsStringAsync();
var cmd = new OleDbCommand(sql, conn);
using (var rdr = await cmd.ExecuteReaderAsync(CommandBehavior.CloseConnection))
{
while (await rdr.ReadAsync())
{
var row = new Dictionary<string, object>();
for (int i = 0; i < rdr.FieldCount; i++)
{
if (!rdr.IsDBNull(i))
row.Add(rdr.GetName(i), rdr.GetValue(i));
}
data.Add(row);
}
}
return Json(data);
}
I am trying to upload a file onto my Drive using Google Drive .NET API v3. My code is below
static string[] Scopes = { DriveService.Scope.Drive,
DriveService.Scope.DriveAppdata,
DriveService.Scope.DriveFile,
DriveService.Scope.DriveMetadataReadonly,
DriveService.Scope.DriveReadonly,
DriveService.Scope.DriveScripts };
static string ApplicationName = "Drive API .NET Quickstart";
public ActionResult Index()
{
UserCredential credential;
using (var stream =
new FileStream("C:/Users/admin1/Documents/visual studio 2017/Projects/TryGoogleDrive/TryGoogleDrive/client_secret.json", FileMode.Open, FileAccess.Read))
{
string credPath = Environment.GetFolderPath(
System.Environment.SpecialFolder.Personal);
credPath = Path.Combine(credPath, ".credentials/drive-dotnet-quickstart.json");
credential = GoogleWebAuthorizationBroker.AuthorizeAsync(
GoogleClientSecrets.Load(stream).Secrets,
Scopes,
"user",
CancellationToken.None,
new FileDataStore(credPath, true)).Result;
Debug.WriteLine("Credential file saved to: " + credPath);
}
// Create Drive API service.
var service = new DriveService(new BaseClientService.Initializer()
{
HttpClientInitializer = credential,
ApplicationName = ApplicationName,
});
// Define parameters of request.
FilesResource.ListRequest listRequest = service.Files.List();
listRequest.PageSize = 10;
listRequest.Fields = "nextPageToken, files(id, name)";
// List files.
IList<Google.Apis.Drive.v3.Data.File> files = listRequest.Execute()
.Files;
Debug.WriteLine("Files:");
if (files != null && files.Count > 0)
{
foreach (var file in files)
{
Debug.WriteLine("{0} ({1})", file.Name, file.Id);
}
}
else
{
Debug.WriteLine("No files found.");
}
var fileMetadata = new Google.Apis.Drive.v3.Data.File()
{
Name = "report.csv",
MimeType = "text/csv",
};
FilesResource.CreateMediaUpload request;
using (var stream = new FileStream("C:/debugging/report.csv",
FileMode.Open))
{
request = service.Files.Create(
fileMetadata, stream, "text/csv");
request.Fields = "id";
request.Upload();
}
var response = request.ResponseBody;
Console.WriteLine("File ID: " + response.Id);
return View();
}
The problem I'm facing is that response is always null. I looked into it a bit further and found that the request returned a 403 resultCode. I also took a look at some other questions on SO this and this but neither were of any help.
Edit: I forgot to mention that the first part of the code is working correctly - it lists all the files in my Drive. Only the second part is not working (the upload file part)
string[] Scopes = { DriveService.Scope.Drive };
Change the Drive scope then delete the file token.json
in vs2017 you can see token.json file in token.json folder when client_secret.json file present.
Try to visit this post from ASP.NET forum.
The same idea as what you want to do in your app, since you are dealing with uploading a file in Google Drive using .net.
You may try to call rest api directly to achieve your requirement :
The quickstart from .net will help you to make requests from/to the Drive API.
Upload Files:
The Drive API allows you to upload file data when create or
updating a File resource.
You can send upload requests in any of the following ways:
Simple upload: uploadType=media. For quick transfer of a small file (5 MB or less). To perform a simple upload, refer to Performing
a Simple Upload.
Multipart upload: uploadType=multipart. For quick transfer of a small file (5 MB or less) and metadata describing the file, all in a
single request. To perform a multipart upload, refer to Performing a
Multipart Upload.
Resumable upload: uploadType=resumable. For more reliable transfer, especially important with large files. Resumable uploads are
a good choice for most applications, since they also work for small
files at the cost of one additional HTTP request per upload. To
perform a resumable upload, refer to Performing a Resumable
Upload.
You may try this code from the documentation on uploading sample file.
var fileMetadata = new File()
{
Name = "photo.jpg"
};
FilesResource.CreateMediaUpload request;
using (var stream = new System.IO.FileStream("files/photo.jpg",
System.IO.FileMode.Open))
{
request = driveService.Files.Create(
fileMetadata, stream, "image/jpeg");
request.Fields = "id";
request.Upload();
}
var file = request.ResponseBody;
Console.WriteLine("File ID: " + file.Id);
You may check the errors you may encounter in this documentation.
Have a look at what request.Upload() returns. For me when I was having this issue it returned:
Insufficient Permission Errors [Message[Insufficient Permission] Location[ - ]
I changed my scope from DriveService.Scope.DriveReadonly to DriveService.Scope.Drive and I was in business.
Change static string[] Scopes = { DriveService.Scope.DriveReadonly }; to static string[] Scopes = { DriveService.Scope.Drive };.
After changes, take a look into token.json file and check does it change its scope from DriveReadonly to Drive.
If you are seeing DriveReadonly then delete the token.json file and run the application again.
I would like to deliver my app with already prefilled data in my realm database. Do I have to simply copy it to the documents directory or is there some other things to do?
Realm's documentation has a section on "Bundling a Realm with an App":
It’s common to seed an app with initial data, making it available to your users immediately on first launch. Here’s how to do this:
First, populate the realm. You should use the same data model as your final, shipping app to create a realm and populate it with the data you wish to bundle with your app. Since realm files are cross-platform, you can use an OS X app (see our JSONImport example) or your iOS app running in the simulator.
In the code where you’re generating this realm file, you should finish by making a compacted copy of the file (see -[RLMRealm writeCopyToPath:error:]). This will reduce the Realm’s file size, making your final app lighter to download for your users.
Drag the new compacted copy of your realm file to your final app’s Xcode Project Navigator.
Go to your app target’s build phases tab in Xcode and add the realm file to the “Copy Bundle Resources” build phase.
At this point, your bundled realm file will be accessible to your app. You can find its path by using [[NSBundle mainBundle] pathForResource:ofType:].
You can either create a read-only realm by calling [RLMRealm realmWithPath:readOnly:error:]. Or, if you’d like to create a writable realm file based on this initial data, you can copy the bundled file to your application’s Documents directory using [[NSFileManager defaultManager] copyItemAtPath:toPath:error:] and then construct your new realm by using [RLMRealm realmWithPath:].
You can refer to our migration sample app for an example of how to use a bundled realm file.
Pre filled Realm-database For Android
Put your realm database in res/raw folder
and execute following code in activity:
// Copying realm database
copyBundledRealmFile(this.getResources().openRawResource(R.raw.default0), "default0.realm");
RealmConfiguration config0 = new RealmConfiguration.Builder()
.name("default0.realm")
.build();
realm = Realm.getInstance(config0);
private String copyBundledRealmFile(InputStream inputStream, String outFileName) {
try {
File file = new File(this.getFilesDir(), outFileName);
FileOutputStream outputStream = new FileOutputStream(file);
byte[] buf = new byte[1024];
int bytesRead;
while ((bytesRead = inputStream.read(buf)) > 0) {
outputStream.write(buf, 0, bytesRead);
}
outputStream.close();
return file.getAbsolutePath();
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
A much easier way is just creating an ad-hoc function to be called just when there is no data on your realm model ("MyModel", in this example), at first app launch:
let realm = try! Realm()
lazy var data: Results<MyModel> = { self.realm.objects(MyModel.self) }()
func populateDefaultData() {
if yourdata.count == 0 {
try! realm.write() {
let defaultData = ["Data1", "Data2", "Data3"]
for data in defaultData {
let newData = MyModel()
newData.data = data
realm.add(newData)
}
}
data = realm.objects(MyModel.self)
}
}
override func viewDidLoad() {
super.viewDidLoad()
populateDefaultData()
}
Is there any quick way/trick to delete around 85K entries for the workflow process history? Trying from the GUI gives a storage issue and to resolve this issue need to bounce the box.
Also trying the PowerTool crashes after a long time. Thought to ask the wider community. appreciate for your thoughts.
Thanks
Vin
Which version of Tridion? 2011?
You could probably get away with a CoreService client app that does this regularly for you. By "PowerTool" I assume you mean the Purge tool?
Also - I would likely contact Customer Support about the errors you see, doesn't seem like using the GUI or the Purge Tool should fail.
If you're on 2011 SP1 you could use the following code:
using System;
using System.ServiceModel;
using System.Xml;
using Tridion.ContentManager.CoreService.Client;
namespace DeleteWorkflowHistory
{
class Program
{
private const string NetTcpEndpoint =
"net.tcp://localhost:2660/CoreService/2011/netTcp";
private static readonly EndpointAddress EndpointAddress =
new EndpointAddress(NetTcpEndpoint);
static void Main(string[] args)
{
var binding = new NetTcpBinding
{
MaxReceivedMessageSize = 2147483647
};
var quota = new XmlDictionaryReaderQuotas
{
MaxStringContentLength = 2147483647,
MaxArrayLength = 2147483647
};
binding.ReaderQuotas = quota;
var client = new SessionAwareCoreServiceClient(binding, EndpointAddress);
Log("Connected to Tridion Content Manager version: " + client.GetApiVersion());
ProcessesFilterData filter = new ProcessesFilterData
{
BaseColumns = ListBaseColumns.IdAndTitle,
ProcessType = ProcessType.Historical
};
foreach (IdentifiableObjectData data in client.GetSystemWideList(filter))
{
var processHistory = data as ProcessHistoryData;
if (processHistory != null)
{
Log("Deleting history: " + processHistory.Id + " / " + processHistory.Title);
client.Delete(processHistory.Id);
}
}
client.Close();
}
private static void Log(string message)
{
Console.WriteLine(string.Format("[{0}] {1}", DateTime.Now.ToString("HH:mm:ss.fff"), message));
}
}
}
N
If you can't use the Core Service, have a look at this blog entry, which describes using the Powershell to force workflow processes to complete. With some very minor modifications, the same technique would work for deleting workflow processes.