How can i save a REST Response to a PDF file? [duplicate] - c#

I have a URL (URL for the live feed from client) which when I hit in browser returns the xml response . I have saved this in text file it`s size is 8 MB.
now my problem is that I need to save this response in xml file on server`s drive. from there I will insert this in database. and request needs to be made using code using http-client or rest-sharp library of c# .net 4.5
I am unsure what should I do for above case. can any body suggest me something

With RestSharp, it's right there in the readme:
var client = new RestClient("http://example.com");
client.DownloadData(request).SaveAs(path);
With HttpClient, it's a bit more involved. Have a look at this blog post.
Another option is Flurl.Http (disclaimer: I'm the author). It uses HttpClient under the hood and provides a fluent interface and lots of convenient helper methods, including:
await "http://example.com".DownloadFileAsync(folderPath, "foo.xml");
Get it on NuGet.

It seems SaveAs was discontinued. You can try this
var client = new RestClient("http://example.com")
byte[] response = client.DownloadData(request);
File.WriteAllBytes(SAVE_PATH, response);

In case you want async version
var request = new RestRequest("/resource/5", Method.GET);
var client = new RestClient("http://example.com");
var response = await client.ExecuteTaskAsync(request);
if (response.StatusCode != HttpStatusCode.OK)
throw new Exception($"Unable to download file");
response.RawBytes.SaveAs(path);

Don't keep the file in memory while reading. Write it directly to the disk.
var tempFile = Path.GetTempFileName();
using var writer = File.OpenWrite(tempFile);
var client = new RestClient(baseUrl);
var request = new RestRequest("Assets/LargeFile.7z");
request.ResponseWriter = responseStream =>
{
using (responseStream)
{
responseStream.CopyTo(writer);
}
};
var response = client.DownloadData(request);
Copied from here https://stackoverflow.com/a/59720610/179017.

Add following NuGet package into the current system
dotnet add package RestSharp
Using Bearer Authentication
// Download file from 3rd party API
[HttpGet("[action]")]
public async Task<IActionResult> Download([FromQuery] string fileUri)
{
// Using rest sharp
RestClient client = new RestClient(fileUri);
client.ClearHandlers();
client.AddHandler("*", () => { return new JsonDeserializer(); });
RestRequest request = new RestRequest(Method.GET);
request.AddParameter("Authorization", string.Format("Bearer " + accessToken),
ParameterType.HttpHeader);
IRestResponse response = await client.ExecuteTaskAsync(request);
if (response.StatusCode == System.Net.HttpStatusCode.OK)
{
// Read bytes
byte[] fileBytes = response.RawBytes;
var headervalue = response.Headers.FirstOrDefault(x => x.Name == "Content-Disposition")?.Value;
string contentDispositionString = Convert.ToString(headervalue);
ContentDisposition contentDisposition = new ContentDisposition(contentDispositionString);
string fileName = contentDisposition.FileName;
// you can write a own logic for download file on SFTP,Local local system location
//
// If you to return file object then you can use below code
return File(fileBytes, "application/octet-stream", fileName);
}
}
Using Basic Authentication
// Download file from 3rd party API
[HttpGet("[action]")]
public async Task<IActionResult> Download([FromQuery] string fileUri)
{
RestClient client = new RestClient(fileUri)
{
Authenticator = new HttpBasicAuthenticator("your user name", "your password")
};
client.ClearHandlers();
client.AddHandler("*", () => { return new JsonDeserializer(); });
RestRequest request = new RestRequest(Method.GET);
IRestResponse response = await client.ExecuteTaskAsync(request);
if (response.StatusCode == System.Net.HttpStatusCode.OK)
{
// Read bytes
byte[] fileBytes = response.RawBytes;
var headervalue = response.Headers.FirstOrDefault(x => x.Name == "Content-Disposition")?.Value;
string contentDispositionString = Convert.ToString(headervalue);
ContentDisposition contentDisposition = new ContentDisposition(contentDispositionString);
string fileName = contentDisposition.FileName;
// you can write a own logic for download file on SFTP,Local local system location
//
// If you to return file object then you can use below code
return File(fileBytes, "application/octet-stream", fileName);
}
}

Related

How to use RestSharp's AddFile() method to send httpContext.Request.Files[0]?

I am using RestSharp to call .NET Web API.
I am sending the uploaded excel file to web api. Below code works perfectly fine on local machine.
But on the server, we don't have permission to save the uploaded file.
I am looking for alternate method for restRequest.AddFile("content", location) that accept HttpPostedFileBase postedFile = httpContext.Request.Files[0].
RestClient restClient = new RestClient("http://localhost:56360");
RestRequest restRequest = new RestRequest("api/excelupload/Upload");
int readWriteTimeout = restRequest.ReadWriteTimeout > 0
? restRequest.ReadWriteTimeout
: ReadWriteTimeout;
restRequest.ReadWriteTimeout = readWriteTimeout;
restRequest.Method = Method.POST;
restRequest.AddHeader("Content-Type", "multipart/form-data");
restRequest.AddFile("content", location);
restRequest.AddParameter("DetailLineNumber", "4");
var response = restClient.Execute(restRequest);
File reading on API.
foreach (var content in provider.Contents)
{
if (!string.IsNullOrWhiteSpace(content.Headers.ContentDisposition.FileName))
{
postedData.File = await content.ReadAsByteArrayAsync();
}
}
I have not used RestSharp for a while. Could you use a Stream? Something like this:
public RestRequest CreateUploadFileRequest(string path, string filename, Stream fileStream)
{
var request = new RestRequest (Method.POST);
request.Timeout = int.MaxValue; //test
request.Resource = "/files/{path}";
request.AddParameter ("path", path, ParameterType.UrlSegment);
//Need to add the "file" parameter with the file name
request.AddParameter ("file", filename);
request.AddFile ("file", s => StreamUtils.CopyStream (fileStream, s), filename);
return request;
}

How to upload a document via API to watson discovery services. ASP.net

I'm using the following API to upload a file to watson discovery services. I'm getting the response as unsupported file format, even though i have provided a valid type.
API:discovery service api
public async Task<ActionResult> Index()
{
using (var httpClient = new HttpClient())
{
//ADD BASIC AUTH
var authByteArray = Encoding.ASCII.GetBytes("{auth key}");
var authString = Convert.ToBase64String(authByteArray);
httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic", authString);
var text = string.Empty;
var uri = "https://gateway.watsonplatform.net/discovery/api/v1/environments/{envid}/collections/{collectionid}/documents?version=2017-11-07";
var content = new MultipartFormDataContent();
var bytes = System.IO.File.ReadAllBytes(Server.MapPath("~/Views/UploadDocument/civilwar-api1.html"));
var file = new StreamContent(new MemoryStream(bytes));
content.Headers.ContentType = MediaTypeHeaderValue.Parse("text/html");
content.Add(new StreamContent(new MemoryStream(bytes)), "file");
var response = await httpClient.PostAsync(uri, content);
var text1 = await response.Content.ReadAsStringAsync();
}
return View();
}
api response as :{
"code" : 415,
"error" : "Unsupported Media Type"
}
As you can see in Watson Developer Cloud, you can use the .NET SDK.
In this repository, you can see examples for using each service from Watson.
The method to add a document:
#region Documents
private void AddDocument()
{
Console.WriteLine(string.Format("\nCalling AddDocument()..."));
using (FileStream fs = File.OpenRead(_filepathToIngest))
{
var result = _discovery.AddDocument(_createdEnvironmentId, _createdCollectionId, _createdConfigurationId, fs as Stream, _metadata);
if (result != null)
{
Console.WriteLine(JsonConvert.SerializeObject(result, Formatting.Indented));
_createdDocumentId = result.DocumentId;
}
else
{
Console.WriteLine("result is null.");
}
}
}
See more about Watson Discovery.
try httpClient.DefaultRequestHeaders
.Accept
.Add(new MediaTypeWithQualityHeaderValue("application/json"));//ACCEPT header

Cannot download a pdf with RestSharp?

I have been struggling to download a simple pdf hosted online using restsharp. I have been playing around with the code for over an hour and all I get are null object results.
The file downloads easily in POSTMAN using a GET and no content header set but still what gives?
Below is the noddy sandbox test I have been experimenting around with:
[TestFixture]
public class Sandbox
{
[Test]
public void Test()
{
var uri = "https://www.nlm.nih.gov/mesh/2018/download/2018NewMeShHeadings.pdf";
var client = new RestClient();
var request = new RestRequest(uri, Method.GET);
//request.AddHeader("Content-Type", "application/octet-stream");
byte[] response = client.DownloadData(request);
File.WriteAllBytes(#"C:\temp\1.pdf", response);
}
}
Update: Return a Stream
var baseUri = "https://www.nlm.nih.gov/mesh/2018/download/";
var client = new RestClient(baseUri);
var request = new RestRequest("2018NewMeShHeadings.pdf", Method.GET);
request.AddHeader("Content-Type", "application/octet-stream");
var tempFile = Path.GetTempFileName();
var stream = File.Create(tempFile, 1024, FileOptions.DeleteOnClose);
request.ResponseWriter = responseStream => responseStream.CopyTo(stream);
var response = client.DownloadData(request);
The stream is now populated with the downloaded data.
Try this:
var uri = "https://www.nlm.nih.gov/mesh/2018/download/";
var client = new RestClient(uri);
var request = new RestRequest("2018NewMeShHeadings.pdf", Method.GET);
//request.AddHeader("Content-Type", "application/octet-stream");
byte[] response = client.DownloadData(request);

how to call web api to download document to website directory using webclient

I am struggling with being able to create a file with its data based on the byte array returned from the WebAPI. The following is my code for making the call to the web api
using (var http = new WebClient())
{
string url = string.Format("{0}api/FileUpload/FileServe?FileID=" + fileID, webApiUrl);
http.Headers[HttpRequestHeader.ContentType] = "application/octet-stream";
http.Headers[HttpRequestHeader.Authorization] = "Bearer " + authCookie.Value;
http.DownloadDataCompleted += Http_DownloadDataCompleted;
byte[] json = await http.DownloadDataTaskAsync(url);
}
The api code is
[HttpGet]
[Route("FileServe")]
[Authorize(Roles = "Admin,SuperAdmin,Contractor")]
public async Task<HttpResponseMessage> GetFile(int FileID)
{
using (var repo = new MBHDocRepository())
{
var file = await repo.GetSpecificFile(FileID);
if (file == null)
{
throw new HttpResponseException(HttpStatusCode.BadRequest);
}
var stream = File.Open(file.PathLocator, FileMode.Open);
HttpResponseMessage response = new HttpResponseMessage(HttpStatusCode.OK);
response.Content = new StreamContent(stream);
response.Content.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue(file.FileType);
return response;
}
}
I receive a byte array as a response however am unable to create the corresponding file from that byte array. I have no idea how to convert the byte array into the relevant file type (such as jpg, or pdf based on file type in the web api). any help will be appreciated.
Alright so there are a few ways of solving your problem firstly, on the server side of things you can either simply send the content type and leave it at that or you can also send the complete filename which helps you even further.
I have removed the code that is specific to your stuff with basic test code, please just ignore that stuff and use it in terms of your code.
Some design notes here:
[HttpGet]
[Route("FileServe")]
[Authorize(Roles = "Admin,SuperAdmin,Contractor")]
public async Task<HttpResponseMessage> GetFileAsync(int FileID) //<-- If your method returns Task have it be named with Async in it
{
using (var repo = new MBHDocRepository())
{
var file = await repo.GetSpecificFile(FileID);
if (file == null)
{
throw new HttpResponseException(HttpStatusCode.BadRequest);
}
var stream = File.Open(file.PathLocator, FileMode.Open);
HttpResponseMessage response = new HttpResponseMessage(HttpStatusCode.OK);
response.Content = new StreamContent(stream);
response.Content.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue(file.FileType);
response.Content.Headers.ContentDisposition = new System.Net.Http.Headers.ContentDispositionHeaderValue("attachment") { FileName=Path.GetFileName(file.PathLocator)};
return response;
}
}
Your client side code has two options here:
static void Main(string[] args)
{
using (var http = new WebClient())
{
string url = string.Format("{0}api/FileUpload/FileServe?FileID={1}",webApiUrl, fileId);
http.Headers[HttpRequestHeader.ContentType] = "application/octet-stream";
http.Headers[HttpRequestHeader.Authorization] = "Bearer " + authCookie.Value;
var response = http.OpenRead(url);
var fs = new FileStream(String.Format(#"C:\Users\Bailey Miller\Downloads\{0}", GetName(http.ResponseHeaders)), FileMode.Create);
response.CopyTo(fs); <-- how to move the stream to the actual file, this is not perfect and there are a lot of better examples
fs.Flush();
fs.Close();
}
}
private static object GetName(WebHeaderCollection responseHeaders)
{
var c_type = responseHeaders.GetValues("Content-Type"); //<-- do a switch on this and return a really weird file name with the correct extension for the mime type.
var cd = responseHeaders.GetValues("Content-Disposition")[0].Replace("\"", ""); <-- this gets the attachment type and filename param, also removes illegal character " from filename if present
return cd.Substring(cd.IndexOf("=")+1); <-- extracts the file name
}

Upload file to Pushbullet in Windows 10 app c#

I'm currently using Pushbullet API and need to upload a file.
I can successfully get an upload url as specified in the docs using this method:
public static async Task<Uploads> GetUploadUrl(string file_name, string file_type)
{
using (var client = new HttpClient())
{
client.DefaultRequestHeaders.Add("Access-Token", AccessToken);
var json = new JObject
{
["file_name"] = file_name,
["file_type"] = file_type
};
var result = await client.PostAsync(new Uri(_uploadUrl, UriKind.RelativeOrAbsolute), new HttpStringContent(json.ToString(), UnicodeEncoding.Utf8, "application/json"));
if (result.IsSuccessStatusCode)
{
var textresult = await result.Content.ReadAsStringAsync();
return JsonConvert.DeserializeObject<Uploads>(textresult);
}
}
return null;
}
The problem is when I try to upload the file. I'm currently using this method:
public static async Task<bool> UploadFile(StorageFile file, string upload_url)
{
try
{
System.Net.Http.HttpClient client = new System.Net.Http.HttpClient();
var content = new MultipartFormDataContent();
if (file != null)
{
var streamData = await file.OpenReadAsync();
var bytes = new byte[streamData.Size];
using (var dataReader = new DataReader(streamData))
{
await dataReader.LoadAsync((uint)streamData.Size);
dataReader.ReadBytes(bytes);
}
var streamContent = new ByteArrayContent(bytes);
content.Add(streamContent);
}
client.DefaultRequestHeaders.Add("Access-Token", AccessToken);
var response = await client.PostAsync(new Uri(upload_url, UriKind.Absolute), content);
if (response.IsSuccessStatusCode)
return true;
}
catch { return false; }
return false;
}
but I get a Http 400 error. What's the right way to upload a file using multipart/form-data in a UWP app?
HTTP 400 error indicates Bad Request, it means the request could not be understood by the server due to malformed syntax. In the other word, the request sent by the client doesn't follow server's rules.
Let's look at the document, and we can find in the example request it uses following parameter:
-F file=#cat.jpg
So in the request, we need to set the name for the uploaded file and the name should be "file". Besides, in this request, there is no need to use access token. So you can change your code like following:
public static async Task<bool> UploadFile(StorageFile file, string upload_url)
{
try
{
System.Net.Http.HttpClient client = new System.Net.Http.HttpClient();
var content = new MultipartFormDataContent();
if (file != null)
{
var streamData = await file.OpenReadAsync();
var bytes = new byte[streamData.Size];
using (var dataReader = new DataReader(streamData))
{
await dataReader.LoadAsync((uint)streamData.Size);
dataReader.ReadBytes(bytes);
}
var streamContent = new ByteArrayContent(bytes);
content.Add(streamContent, "file");
}
//client.DefaultRequestHeaders.Add("Access-Token", AccessToken);
var response = await client.PostAsync(new Uri(upload_url, UriKind.Absolute), content);
if (response.IsSuccessStatusCode)
return true;
}
catch { return false; }
return false;
}
Then your code should be able to work. You will get a 204 No Content response and UploadFile method will return true.

Categories