We were upgrading to the new logic specified by ConvertAPI. But the framework used by us is 4 because of which System.Net.Http(HttpResponseMessage, HttpClient ,MultipartFormDataContent ,StreamContent ,StringContent) classes are not being found. Even added System.Net.Http reference. But still the same error persists.
Can someone suggest some workaround for this? How to use ConvertApi in C# for .Net Framework 4?
Just use WebClient instead of HttpClient for quick file upload. To run the demo below you will need to replace file paths and set your secret instead of xxxxx in endpoint url. Also we should set accept:application/octet-stream header to get response as data stream instead of json.
class Program
{
static void Main(string[] args)
{
const string fileToConvert = #"C:\Projects\_temp\test1.docx";
const string fileToSave = #"C:\Projects\_temp\test1.pdf";
try
{
using (var client = new WebClient())
{
client.Headers.Add("accept", "application/octet-stream");
var resultFile = client.UploadFile(new Uri("https://v2.convertapi.com/docx/to/pdf?Secret=xxxxx"), fileToConvert);
File.WriteAllBytes(fileToSave, resultFile );
Console.WriteLine("File converted successfully");
}
}
catch (WebException e)
{
Console.WriteLine("Status Code : {0}", ((HttpWebResponse)e.Response).StatusCode);
Console.WriteLine("Status Description : {0}", ((HttpWebResponse)e.Response).StatusDescription);
Console.WriteLine("Body : {0}", new StreamReader(e.Response.GetResponseStream()).ReadToEnd());
}
Console.ReadLine();
}
}
Related
I am currently working with S3 and need to extract an S3 resource which has a timeout for streaming, so that the client cannot use the URL after a specific amount of time.
I have already used some code provided in the documentation for "Presigned Object URL Using AWS SDK for .NET".
The code will provide a temporary URL which can be used to download an S3 resource by anyone...but within a specific time limit.
I have also used the Amazon S3 Explorer for Visual Studio, but it doesn't support URL generation for resources embedded with AWSKMS key.
Also tried deleting the KMS Key for the S3 folder, but that is throwing an error.
If there is a possible link for deleting KMS keys can you also include it in your answers.
//Code Start
using Amazon;
using Amazon.S3;
using Amazon.S3.Model;
using System;
namespace URLDownload
{
public class Class1
{
private const string bucketName = "some-value";
private const string objectKey = "some-value";
// Specify your bucket region (an example region is shown).
private static readonly RegionEndpoint bucketRegion = RegionEndpoint.USEast1;
private static IAmazonS3 s3Client;
public static void Main()
{
s3Client = new AmazonS3Client(bucketRegion);
string urlString = GeneratePreSignedURL();
Console.WriteLine(urlString);
Console.Read();
}
static string GeneratePreSignedURL()
{
string urlString = "";
try
{
//ServerSideEncryptionMethod ssem = new ServerSideEncryptionMethod("AWSKMS");
GetPreSignedUrlRequest request1 = new GetPreSignedUrlRequest
{
BucketName = bucketName,
Key = objectKey,
Expires = DateTime.Now.AddMinutes(5),
Verb = 0,
ServerSideEncryptionKeyManagementServiceKeyId = "some-value",
ServerSideEncryptionMethod = ServerSideEncryptionMethod.AWSKMS
};
urlString = s3Client.GetPreSignedURL(request1);
}
catch (AmazonS3Exception e)
{
Console.WriteLine("Error encountered on server. Message:'{0}' when writing an object", e.Message);
}
catch (Exception e)
{
Console.WriteLine("Unknown encountered on server. Message:'{0}' when writing an object", e.Message);
}
return urlString;
}
}
}
SignatureDoesNotMatch
The request signature we calculated does not match the signature you provided. Check your key and signing method.
AKIA347A6YXQ3XM4JQ7A
This is the error that I am getting when I am trying to access the generated URL and that is probably because the AWSKMS authentication is having some issue.
I see it's been a couple of years, but did have an answer for this one? One thing that your code snippet seems to be missing is V4 signature flag set to true:
AWSConfigsS3.UseSignatureVersion4 = true;
Sources:
https://aws.amazon.com/blogs/developer/generating-amazon-s3-pre-signed-urls-with-sse-part-1/
https://aws.amazon.com/blogs/developer/generating-amazon-s3-pre-signed-urls-with-sse-kms-part-2/
You also need to make sure you're providing x-amz-server-side-encryption and x-amz-server-side-encryption-aws-kms-key-id headers on your upload request
Trying to make Android chooser to display available actions for user to launch a PDF file which is stored in my local folder.
When I pass the file name like /data/user/0/myappappname/files/output.pdf , (which exsists, of course), I get a nice chooser with all the apps that can accept a pdf file. But when I pick any of them, I get an error (from external app) The document path is not valid. No exception is thrown.
Then I tried (for testing purposes) to set fname to something like /storage/emulated/0/Download/TLCL.pdf (file also exists), and everything works fine.
At first, I thought that this has something to do with file permissions (since first path is private to my app), but then I found flag ActivityFlags.GrantReadUriPermission built exactly for purpose of temporarily granting file access to other apps. Still same results.
Since this is a Xamarin.forms project, I am limited in choice of file creation locations (I use PCLStorage, which always writes to app-private, local folder), so I don't have an option of generating files in /Documents, /Downloads etc.
I am obviously doing something wrong. Any ideas appreciated.
Is there an option to get full path from system, including the /storage/emulated/0 part (or whatever that would be on other devices)? Maybe that would help?
Piece of code:
(mimeType is defined as "application/pdf" earlier)
public async Task<bool> LaunchFile(string fname, string mimeType)
{
var uri = Android.Net.Uri.Parse("file://" + fname );
var intent = new Intent(Intent.ActionView);
intent.SetDataAndType(uri, mimeType);
intent.SetFlags(ActivityFlags.ClearWhenTaskReset | ActivityFlags.NewTask | ActivityFlags.GrantReadUriPermission );
try
{
Forms.Context.StartActivity(Intent.CreateChooser(intent, "ChooseApp"));
return true;
}
catch (Exception ex)
{
Debug.WriteLine("LaunchFile: " + ex.Message);
return false;
}
My solution to this, which may not be exactly what you want, is to generate a file (in my case a zip file), export it to a public folder, and use that file for the chooser.
Using these:
private readonly string PublicDocsPath = Android.OS.Environment.ExternalStorageDirectory.AbsolutePath + "/AppName";
private readonly string PrivateDocsPath = System.Environment.GetFolderPath(System.Environment.SpecialFolder.ApplicationData);
and some basic functions:
public Stream GetOutputStream(string destFilePath)
{
string destFolderPath = Path.GetDirectoryName(destFilePath);
if (!Directory.Exists(destFolderPath))
Directory.CreateDirectory(destFolderPath);
return new FileStream(destFilePath, FileMode.Create, FileAccess.Write, FileShare.None);
}
public Stream GetInputStream(string sourceFilePath)
{
if (!File.Exists(sourceFilePath)) throw new FileNotFoundException();
string sourceFolderPath = Path.GetDirectoryName(sourceFilePath);
return new FileStream(sourceFilePath, FileMode.Open, FileAccess.Read, FileShare.Read);
}
You can copy your file to your public folder (or subfolders, you just have to assemble the path) and use that file for your chooser:
public void SendEmail(string subject, string body, string recipient, string mimeType, string attachmentFilePath, string activityTitle)
{
var emailIntent = new Intent(Intent.ActionSendMultiple);
if (string.IsNullOrEmpty(subject)) throw new ArgumentException();
emailIntent.PutExtra(Intent.ExtraSubject, subject);
if (!string.IsNullOrEmpty(recipient))
emailIntent.PutExtra(Intent.ExtraEmail, new[] { recipient });
if (!string.IsNullOrEmpty(body))
emailIntent.PutExtra(Intent.ExtraText, body);
if (!string.IsNullOrEmpty(attachmentFilePath))
{
var file = new Java.IO.File(attachmentFilePath);
file.SetReadable(true, true);
var uri = Android.Net.Uri.FromFile(file);
emailIntent.PutParcelableArrayListExtra(Intent.ExtraStream, new List<IParcelable>(){uri});
}
emailIntent.SetType(mimeType);
_activity.StartActivity(Intent.CreateChooser(emailIntent, activityTitle));
}
This chooser specifically lets the user send their file via email or google drive , but you can assemble it however you want. The attachmentFilePath of this function is the same as the string passed into the GetOutputStream function above.
we're using Acr.IO rather than PCLStorage and I recall that has a property that'll return the fullpath for you.
The code we're using is below, but I wonder if you're simply missing "file://" off the start of your path, as I noticed thats in our code, as well as this previous stackoverflow answer to a similar question as this one, open a PDF in Xamarin.Forms (Android)
We're using a dependency FileService on Android and using this code to open PDFs:
public void OpenNatively(string filePath) {
Android.Net.Uri uri;
if (filePath.StartsWithHTTP()) {
uri = Android.Net.Uri.Parse(filePath);
}
else {
uri = Android.Net.Uri.Parse("file:///" + filePath);
}
Intent intent = new Intent(Intent.ActionView);
var extension = filePath.Substring(filePath.LastIndexOf(".")+1);
if (extension == "ppt" || extension == "pptx") {
extension = "vnd.ms-powerpoint";
}
var docType = "application/" + extension;
intent.SetDataAndType(uri, docType);
intent.SetFlags(ActivityFlags.ClearWhenTaskReset | ActivityFlags.NewTask);
try {
Xamarin.Forms.Forms.Context.StartActivity(intent);
}
catch (Exception e) {
Toast.MakeText(Xamarin.Forms.Forms.Context, "No Application found to view " + extension.ToUpperInvariant() + " files.", ToastLength.Short).Show();
}
}
I'm trying to download a simple xml file and save it to the users local profile. When trying to download (i don't think this has anything to do with the saving location but i'm not 100% sure) i get the following exception on the webclient.
System.InvalidOperationException
My code is as follows;
public void downloadProxy() {
string url = Properties.Settings.Default.url;
string path = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "/netsettings/proxies.xml");
try
{
WebClient GrabFile = new WebClient();
GrabFile.DownloadFile(url, path);
}
catch (WebException webEx)
{
if (webEx.Status == WebExceptionStatus.ConnectFailure)
{
Console.WriteLine("Are you behind a firewall? If so, go through the proxy server.");
}
}
}
If you are on a Windows operating system, use a backslash (not a slash) as folder separator:
\netsettings\proxies.xml
this is my first post on this site and I searched high and wide to get my code to work.
Like the title says, it's a WinRT App and I'm having difficulty with File IO. What I want to do is read in a text file stored in a folder that is inside the application installation directory and that contains lines of data that I'll feed into an List<>.
public static async void GetStations()
{
try
{
using (var stream = await Windows.Storage.ApplicationData.Current.LocalFolder.OpenStreamForReadAsync(#"MyApp\Data\file.txt"))
{
using (var streamReader = new StreamReader(stream))
{
while (streamReader.Peek() >= 0)
{
string line = await streamReader.ReadLineAsync();
//do something with
}
}
}
}
catch (Exception e)
{
...
}
finally
{
...
}
}
the problem is I am getting file not found errors when trying to run it. Can anyone help? If you require that I post more information, I can...
Thanks in advance.
If you are distributing your file as a part of your application package then Package.Current.InstalledLocation is the right location. ApplicationData.Current.LocalFolder contains only files that have been put there by your application.
The correct code would be:
public static async void GetStations()
{
try
{
using (var stream = await Windows.ApplicationModel.Package.Current.InstalledLocation.OpenStreamForReadAsync(#"Data\file.txt"))
{
using (var streamReader = new StreamReader(stream))
{
while (streamReader.Peek() >= 0)
{
string line = await streamReader.ReadLineAsync();
//do something with
}
}
}
}
catch (Exception e)
{
//...
}
finally
{
//...
}
}
The file must be included in you project inside Data folder and have Build Action set to Content.
Instead of opening from ApplicationData, you probably need:
Windows.ApplicationModel.Package.Current.InstalledLocation.GetFileAsync
This will get the file in the package's installation folder, instead of the Application's Data folder.
I wrote a program to download files from a website by using WebClient.DownloadFile().
public static void downWeb()
{
WebClient myWebClient = new WebClient();
path = Environment.GetFolderPath(Environment.SpecialFolder.Desktop);
if (!Directory.Exists(path))
{
Directory.CreateDirectory(path);
}
if (add() == 1)
{
Console.WriteLine("Response is " + add());
Console.WriteLine("Downloading File = " + dynFileName + "....");
myWebClient.DownloadFile(fullAddress, (path + dynFileName));
}
}
public static int add()
{
string url = fullAddress;
WebRequest webRequest = WebRequest.Create(url);
WebResponse webResponse;
try
{
webResponse = webRequest.GetResponse();
}
catch
{
return 0;
}
return 1;
}
downWeb() is a function to be called in the Main() function.
add() is a function that tests the availability of the file on server. If response is positive, it returns value "1".
fullAddress = address from where the files has to downloaded. It's changing every time before calling this function in a loop present in Main().
When I start my application, I ask the user to:
1) Enter URL to be downloaded i.e. www.1234.com\samplefiles\pg-1.pdf
2) Number of pages to be downloaded (By changing the above filename no. in a loop as rest of the url is same on server)
Now my problem is when I am downloading files, first file downloads PERFECTLY, but the second download is never finished. It says "REQUEST TIMED OUT", and my application closes.
I don't know what's happening here.
How can this be solved?
http://msdn.microsoft.com/en-us/library/system.net.httpwebrequest.getresponse.aspx
You must call the Close method to close the stream and release the connection. Failure to do so may cause your application to run out of connections.
Your problem likely is related to the fact that you do not dispose of your connections. You should make sure that you don't leak them.