Upload file on Dropbox using REST api - c#

Below code uploads files on a server with same name, size and file type (like it's uploading a dummy file). But when do I try to view it, it shows noting. When I try to upload a .txt file it works. What's wrong?
public static void UploadFile(string accessToken,string path,HttpPostedFileBase file)
{
try
{
var client = new RestClient("https://content.dropboxapi.com/1/files_put/auto/Abc/" + file.FileName);
var request = new RestRequest(Method.PUT);
request.AddHeader("Authorization", "Bearer " + accessToken);
request.AddHeader("Content-Type", file.ContentType);
//request.AddHeader("Content-Length", file.ContentLength.ToString());
request.AddFile("file", path);
IRestResponse response = client.Execute(request);
}
catch (Exception ex)
{
throw ex;
}
}

I assume from the classes I see that you're using RestSharp? I'm not all that familiar, but from a quick search, it doesn't look like AddFile does what you want. (That sets up a multipart form upload, which is not what the Dropbox API expects.)
Instead of request.AddFile(...), I think you want something like this (completely untested):
// Get a byte array of the file content. Note that this involves reading
// the entire file into memory! I couldn't immediately find a way to work
// with the stream itself in RestSharp.
MemoryStream target = new MemoryStream();
file.InputStream.CopyTo(target);
byte[] data = target.ToArray();
// Send those bytes as the body of your HTTP request.
request.AddParameter("application/octet-stream", data, ParameterType.RequestBody);

Related

How to download rest api response content into excel using windows forms application c#

I'm trying to download REST API response content as (original format) excel (.xlsx)
My request url is :- https://www.connect2nse.com/extranet-api/member/file/download/1.0?segment=CM&folderPath=/Reports&filename=07141_AR1_Dec22.xlsx
And I'm downloading the 07141_AR1_Dec22.xlsx file.
So, I have used this method to return the response content
public static string DownloadFileName()
{
try
{
var client = new RestClient("https://www.connect2nse.com/extranet-api/member/file/download/1.0?segment=CM&folderPath=/Reports&filename=07141_AR1_Dec22.xlsx");
client.Timeout = -1;
var request = new RestRequest(Method.GET);
request.AddHeader("Authorization", "Bearer eyJhbGciOweSUzI1NiJ9.eyJtZW1iZXJDZCI6IjA3MTQxIiwic3ViIjoiMDcxNDEiLCJsb2dpbklkIjoiYm5yaG8xIiwiaXNzIjoiYm5yaG8xIiwiZXhwIjoxNjc0ODA0NDE0LCJpYXQiOjE2NzQ4MDA4MTQsImp0aSI6ImEwY2U3NjNkLWY1OWUtNDY2Yy1hMmMwLTUwNGQwZDgzOTQwYiJ9.UCnkkvTTi9fZjWWak5deXgxPEqMG16FQP4Cy_u1cR0hQb-xQ4LAhbfpMtFz1WXQ4fz7ZmRhkR1i9JXY4w32lzQ");
request.AddHeader("Cookie", "HttpOnly");
var body = #"";
request.AddParameter("text/plain", body, ParameterType.RequestBody);
IRestResponse response = client.Execute(request);
//Console.WriteLine(response.Content);
return response.Content;
}
catch (Exception)
{
throw;
}
}
And I'm calling this method in btnDownload_Click event in windows forms application
private void btnDownload_Click(object sender, EventArgs e)
{
string downloadfile = DownloadFileName();
string _tradelogfile = Application.StartupPath + "\\07141_AR1_Dec22.xlsx";
using (System.IO.StreamWriter file = new System.IO.StreamWriter(_tradelogfile, true))
{
file.WriteLine(downloadfile);
}
}
The DownloadFileName method is returning the output like below image
So if I keep execute the program the file is downloading at specified location
Like below example
While I'm opening the file it is throwing warning errors and file is not opening like below
In the postman response also I'm getting the response like below image
And I have read this article for better understanding but it not helped to me.
Please suggest me where I did the mistake and how to save(download) this REST API response content as excel format(.xlsx).
Should I use any dll or is my code issue ?
Please suggest.

Send a 'Stream' over a PutAsync request

I'm trying my hand at .NET Core but I'm stuck trying to convert multipart/form-data to an application/octet-stream to send via a PUT request. Anybody have any expertise I could borrow?
[HttpPost("fooBar"), ActionName("FooBar")]
public async Task<IActionResult> PostFooBar() {
HttpResponseMessage putResponse = await _httpClient.PutAsync(url, HttpContext.Request.Body);
}
Update: I think I might have two issues here:
My input format is multipart/form-data so I need to split out the file from the form data.
My output format must be application-octet stream but PutAsync expects HttpContent.
I had been trying to do something similar and having issues. I needed to PUT large files (>1.5GB) to a bucket on Amazon S3 using a pre-signed URL. The implementation on Amazon for .NET would fail for large files.
Here was my solution:
static HttpClient client = new HttpClient();
client.Timeout = TimeSpan.FromMinutes(60);
static async Task<bool> UploadLargeObjectAsync(string presignedUrl, string file)
{
Console.WriteLine("Uploading " + file + " to bucket...");
try
{
StreamContent strm = new StreamContent(new FileStream(file, FileMode.Open, FileAccess.Read));
strm.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue("application/octet-stream");
HttpResponseMessage putRespMsg = await client.PutAsync(presignedUrl, strm);
}
catch (Exception e)
{
Console.WriteLine(e.Message);
return false;
}
return true;
}
Turns out Request has a Form property that contains a Files property that has an OpenReadStream() function on it to convert it into a stream. How exactly I was supposed to know that, I'm not sure.
Either way, here's the solution:
StreamContent stream = new StreamContent(HttpContext.Request.Form.Files[0].OpenReadStream());
HttpResponseMessage putResponse = await _httpClient.PutAsync(url, stream);

https://do.convertapi.com/Pdf2PowerPoint without providing physical file location

I am calling API
https://do.convertapi.com/Pdf2PowerPoint
Their website for the API details is
https://www.convertapi.com/
To upload the file in their C# documentation they have used client.UploadFile() function which expects file name parameter from physical location. in my case i have bytes of PDF file coming on the fly without storing that to physical location and I want to upload that bytes instead. I am using client.UploadData() function which expects byte array and I have provide that. but their API is throwing error and is asking to provide File name which is must.
I think Developers of API would only be able to answer. But if you guys have any idea if I am doing any mistake to upload file. please suggest your workaround.
Please find my code below as requested
var client = new WebClient();
var data = new NameValueCollection();
data.Add("OutputFileName", "TestOutput.pptx"); //Optional
data.Add("File", "Revised.pdf");
data.Add("ApiKey", "484700111"); //API Key must be set if you purchased membership with credits. Please login to your control panel to find out your API Key http://www.convertapi.com/prices
try
{
client.QueryString.Add(data);
client.Headers.Add("Content-Type", "application/x-www-form-urlencoded");
//I am using ReadAllBytes Approach for now as in my practical scenario I am going to get bytes instead of sending file from Physical location
byte[] Arr = File.ReadAllBytes(#"D:\PPTTest\Level I and II Revised.pdf");
// Error here : File Parameter can not be null
var response = client.UploadData("https://do.convertapi.com/Pdf2PowerPoint", Arr);
var responseHeaders = client.ResponseHeaders;
var path = Path.Combine(#"D:\PPTTest\", responseHeaders["OutputFileName"]);
File.WriteAllBytes(path, response);
//Console.WriteLine("The conversion was successful! The word file {0} converted to PDF and saved at {1}", fileToConvert, path);
}
catch (WebException e)
{
Console.WriteLine("Exception Message :" + e.Message);
if (e.Status == WebExceptionStatus.ProtocolError)
{
Console.WriteLine("Status Code : {0}", ((HttpWebResponse)e.Response).StatusCode);
Console.WriteLine("Status Description : {0}", ((HttpWebResponse)e.Response).StatusDescription);
}
}
Thanks,
Hira
Code taken from this post. You have to upload file with multipart/form-data request like this:
HttpClient httpClient = new HttpClient();
MultipartFormDataContent form = new MultipartFormDataContent();
form.Add(new StringContent(username), "username");
form.Add(new StringContent(useremail), "email");
form.Add(new StringContent(password), "password");
form.Add(new ByteArrayContent(imagebytearraystring, 0, imagebytearraystring.Count()), "profile_pic", "hello1.jpg");
HttpResponseMessage response = await httpClient.PostAsync("PostUrl", form);

ASP.NET Web API Streaming a file

I am using Web API to serve the requests for files. File may be on disk or on some other server. The API controller sends a forward request or reads the file from the system and returns it.
public HttpResponseMessage GetResponse(string uri, HttpRequestMessage request)
{
HttpResponseMessage response = new HttpResponseMessage();
try
{
string newUrl = MapUrl(uri);
Stream responseStream = CreateResponse(request, newUrl);
response.Content = new StreamContent(responseStream);
return response;
}
catch (Exception ex)
{
response.StatusCode = HttpStatusCode.NotFound;
response.Content = new StringContent(ex.ToString());
return response;
}
}
CreateResponse() either returns a FileStream or GetResponseStream() based on the current configuration.
No Content-Length header is being added as the file is being streamed, in the response headers I see Transfer-Encoding: chunked header as expected.
But in case the file has to be served by reading from the filesystem IIS automatically adds the Content-Length header - which should not have happened as the file is being read as a stream by the code,
return new FileStream(newUrl, FileMode.Open);
any custom headers added show up confirming response was sent by the code and not IIS directly.
In global.asax routes.RouteExistingFiles = true;

How can I send a File over a REST API?

I am trying to send a file to a server over a REST API. The file could potentially be of any type, though it can be limited in size and type to things that can be sent as email attachments.
I think my approach will be to send the file as a binary stream, and then save that back into a file when it arrives at the server. Is there a built in way to do this in .Net or will I need to manually turn the file contents into a data stream and send that?
For clarity, I have control over both the client and server code, so I am not restricted to any particular approach.
I'd recommend you look into RestSharp
http://restsharp.org/
The RestSharp library has methods for posting files to a REST service. (RestRequst.AddFile()). I believe on the server-side this will translate into an encoded string into the body, with the content-type in the header specifying the file type.
I've also seen it done by converting a stream to a base-64 string, and transferring that as one of the properties of the serialized json/xml object. Especially if you can set size limits and want to include file meta-data in the request as part of the same object, this works really well.
It really depends how large your files are though. If they are very large, you need to consider streaming, of which the nuances of that is covered in this SO post pretty thoroughly: How do streaming resources fit within the RESTful paradigm?
You could send it as a POST request to the server, passing file as a FormParam.
#POST
#Path("/upload")
//#Consumes(MediaType.MULTIPART_FORM_DATA)
#Consumes("application/x-www-form-urlencoded")
public Response uploadFile( #FormParam("uploadFile") String script, #HeaderParam("X-Auth-Token") String STtoken, #Context HttpHeaders hh) {
// local variables
String uploadFilePath = null;
InputStream fileInputStream = new ByteArrayInputStream(script.getBytes(StandardCharsets.UTF_8));
//System.out.println(script); //debugging
try {
uploadFilePath = writeToFileServer(fileInputStream, SCRIPT_FILENAME);
}
catch(IOException ioe){
ioe.printStackTrace();
}
return Response.ok("File successfully uploaded at " + uploadFilePath + "\n").build();
}
private String writeToFileServer(InputStream inputStream, String fileName) throws IOException {
OutputStream outputStream = null;
String qualifiedUploadFilePath = SIMULATION_RESULTS_PATH + fileName;
try {
outputStream = new FileOutputStream(new File(qualifiedUploadFilePath));
int read = 0;
byte[] bytes = new byte[1024];
while ((read = inputStream.read(bytes)) != -1) {
outputStream.write(bytes, 0, read);
}
outputStream.flush();
}
catch (IOException ioe) {
ioe.printStackTrace();
}
finally{
//release resource, if any
outputStream.close();
}
return qualifiedUploadFilePath;
}
Building on to #MutantNinjaCodeMonkey's suggestion of RestSharp. My use case was posting webform data from jquery's $.ajax method into a web api controller. The restful API service required the uploaded file to be added to the request Body. The default restsharp method of AddFile mentioned above caused an error of The request was aborted: The request was canceled. The following initialization worked:
// Stream comes from web api's HttpPostedFile.InputStream
(HttpContext.Current.Request.Files["fileUploadNameFromAjaxData"].InputStream)
using (var ms = new MemoryStream())
{
fileUploadStream.CopyTo(ms);
photoBytes = ms.ToArray();
}
var request = new RestRequest(Method.PUT)
{
AlwaysMultipartFormData = true,
Files = { FileParameter.Create("file", photoBytes, "file") }
};
Detect the file/s being transported with the request.
Decide on a path where the file will be uploaded (and make sure CHMOD 777 exists for this directory)
Accept the client connect
Use ready library for the actual upload
Review the following discussion:
REST file upload with HttpRequestMessage or Stream?
First, you should login to the server and get an access token.
Next, you should convert your file to stream and post the stream:
private void UploadFile(FileStream stream, string fileName)
{
string apiUrl = "http://example.com/api";
var formContent = new MultipartFormDataContent
{
{new StringContent(fileName),"FileName"},
{new StreamContent(stream),"formFile",fileName},
};
using HttpClient httpClient = new HttpClient();
httpClient.DefaultRequestHeaders.Add("Authorization", accessToken);
var response = httpClient.PostAsync(#$"{apiUrl}/FileUpload/save", formContent);
var result = response.Result.Content.ReadAsStringAsync().Result;
}
In this example, we upload the file to http://example.com/api/FileUpload/save and the controller has the following method in its FileUpload controller:
[HttpPost("Save")]
public ActionResult Save([FromForm] FileContent fileContent)
{
// ...
}
public class FileContent
{
public string FileName { get; set; }
public IFormFile formFile { get; set; }
}

Categories

Resources