Corresponding web api function to accept file - asp.net

I am trying to upload file using retrofit, send it to the server side and save that file in my uploads folder.
This is my retrofit API instance:
#Multipart
#POST("file/uploaddocument")
Call<ResponseBody> uploadFile(#Part MultipartBody.Part file );
UploadFile:
private void uploadFile(Uri fileUri) {
// create upload service client
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(BASE_URL)
.addConverterFactory(GsonConverterFactory.create())
.build();
MyApiEndpointInterface apiService =
retrofit.create(MyApiEndpointInterface.class);
// https://github.com/iPaulPro/aFileChooser/blob/master/aFileChooser/src/com/ipaulpro/afilechooser/utils/FileUtils.java
// use the FileUtils to get the actual file by uri
File file = Utils.getFileForUri(fileUri);
// create RequestBody instance from file
RequestBody requestFile =
RequestBody.create(
MediaType.parse(getContentResolver().getType(fileUri)),
file
);
// MultipartBody.Part is used to send also the actual file name
MultipartBody.Part body =
MultipartBody.Part.createFormData("file", file.getName(), requestFile);
// finally, execute the request
Call<ResponseBody> call = apiService.uploadFile(body);
call.enqueue(new Callback<ResponseBody>() {
#Override
public void onResponse(Call<ResponseBody> call,
Response<ResponseBody> response) {
UploadProgressDialog.dismiss();
Log.v("Upload", "success");
}
#Override
public void onFailure(Call<ResponseBody> call, Throwable t) {
UploadProgressDialog.dismiss();
Log.e("Upload error:", t.getMessage());
}
});
}
And I'm calling this method on button click as :
uploadFile(myfileuri);
This is my Web API call(Is this correct ? If not how to accept the image from client side ?)
<HttpPost>
<Route("api/File/UploadDocument", Name:="UploadDocument")>
Public Function Upload() As HttpResponseMessage
Try
Dim UploadedPath As String = HttpContext.Current.Server.MapPath("~/UploadedFiles")
Dim httpRequest = HttpContext.Current.Request
If httpRequest.Files.Count > 0 Then
For Each file As String In httpRequest.Files
Dim postedFile = httpRequest.Files(file)
postedFile.SaveAs(UploadedPath + "/")
Next
Else
End If
Dim message = Request.CreateResponse(HttpStatusCode.OK, "True")
Return message
Catch ex As Exception
Return Request.CreateErrorResponse(HttpStatusCode.BadRequest, ex)
End Try
End Function

This is how I done it...Posting here so that some one else might be found it useful
<HttpPost, Route("api/UploadFile")>
Public Function Post() As HttpResponseMessage
Try
Dim httpRequest = HttpContext.Current.Request
If httpRequest.Files.Count < 1 Then
Return Request.CreateResponse(HttpStatusCode.BadRequest)
End If
For Each file As String In httpRequest.Files
Dim postedFile = httpRequest.Files(file)
Dim filePath = HttpContext.Current.Server.MapPath("~/UploadedFiles/" + postedFile.FileName)
' NOTE: To store in memory use postedFile.InputStream
postedFile.SaveAs(filePath)
Next
Return Request.CreateResponse(HttpStatusCode.NoContent)
Catch ex As Exception
Return Request.CreateErrorResponse(HttpStatusCode.BadRequest, ex)
End Try
End Function

Related

Using RestSharp to aend files between to API's on Kubernetes

So I have to API's running on Kubernetes. One has a controller function as such:
string filePath = "/blobs/data/runsession/" + folderName;
if (!Directory.Exists(filePath))
return null;
var tempFile = Path.Combine(Path.GetTempPath(), guid.ToString());
logger.Info("GetTempPath()" + Path.GetTempPath());
logger.Info("Temp path is: " + tempFile);
ZipFile.CreateFromDirectory(filePath, (tempFile + ".zip"));
byte[] fileBytes = File.ReadAllBytes(tempFile + ".zip");
HelpMethods.GetNetworkTimeStamp("Stop", 2);
return fileBytes;
This controller method works fine and when I call it from postman it returns a file.
Now in the other API I want to call this function from one of my service classes as such:
public async Task<byte[]> DownloadRunSession(string foldername)
{
try
{
var request = new RestRequest($"blob/{foldername}")
{
Timeout = -1,
};
var response = await client.ExecuteGetAsync(request);
if (!response.IsSuccessful)
{
Console.WriteLine("File download failed");
Console.WriteLine(response.Content.ToString());
return null;
}
return response.RawBytes;
}catch(Exception e)
{
Console.WriteLine(e.Message);
Console.WriteLine(e.StackTrace);
return null;
}
Now the server logs on the API that sends the file Give me a status 200 but says "the application aborted the connection", and the API that is supposed to receive the file gets no response and the response variable is always "null".
Any one that has had a similar dilemma and knows how to solve it?

download file from google drive using asp.net

I am trying download file from google drive using the code below:
public static Boolean downloadFile(string downloadurl, string _saveTo)
{
if (!String.IsNullOrEmpty(downloadurl))
{
try
{
var x = service.HttpClient.GetByteArrayAsync(downloadurl);
byte[] arrBytes = x.Result;
System.IO.File.WriteAllBytes(_saveTo, arrBytes);
return true;
}
catch (Exception e)
{
Console.WriteLine("An error occurred: " + e.Message);
return false;
}
}
else
{
// The file doesn't have any content stored on Drive.
return false;
}
}
On debugging the above code throwing exception as below:
?service.HttpClient.GetByteArrayAsync(downloadurl)
Id = 10, Status = WaitingForActivation, Method = "{null}", Result = "{Not yet computed}"
AsyncState: null
CancellationPending: false
CreationOptions: None
Exception: null
Id: 10
Result: null
Status: WaitingForActivation
I am trying to do it from my Service account created using Google API Console.
and the exception detail is as follows:
System.NullReferenceException was caught
HResult=-2147467261
Message=Object reference not set to an instance of an object.
Source=System.Net.Http
StackTrace:
at System.Net.Http.Headers.HttpRequestHeaders.AddHeaders(HttpHeaders sourceHeaders)
at System.Net.Http.HttpClient.PrepareRequestMessage(HttpRequestMessage request)
at System.Net.Http.HttpClient.SendAsync(HttpRequestMessage request, HttpCompletionOption completionOption, CancellationToken cancellationToken)
at System.Net.Http.HttpClient.GetAsync(Uri requestUri, HttpCompletionOption completionOption, CancellationToken cancellationToken)
at System.Net.Http.HttpClient.GetContentAsync[T](Uri requestUri, HttpCompletionOption completionOption, T defaultValue, Func`2 readAs)
at System.Net.Http.HttpClient.GetByteArrayAsync(Uri requestUri)
at System.Net.Http.HttpClient.GetByteArrayAsync(String requestUri)
You can try this.
link
using Google.Apis.Authentication;
using Google.Apis.Drive.v2;
using Google.Apis.Drive.v2.Data;
using System.Net;
public class MyClass {
public static System.IO.Stream DownloadFile(
IAuthenticator authenticator, File file) {
if (!String.IsNullOrEmpty(file.DownloadUrl)) {
try {
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(
new Uri(file.DownloadUrl));
authenticator.ApplyAuthenticationToRequest(request);
HttpWebResponse response = (HttpWebResponse) request.GetResponse();
if (response.StatusCode == HttpStatusCode.OK) {
return response.GetResponseStream();
} else {
Console.WriteLine(
"An error occurred: " + response.StatusDescription);
return null;
}
} catch (Exception e) {
Console.WriteLine("An error occurred: " + e.Message);
return null;
}
} else {
// The file doesn't have any content stored on Drive.
return null;
}
}
}
Code using the Google .net client library
Service account:
string[] scopes = new string[] {DriveService.Scope.Drive}; // Full access
var keyFilePath = #"c:\file.p12" ; // Downloaded from https://console.developers.google.com
var serviceAccountEmail = "xx#developer.gserviceaccount.com"; // found https://console.developers.google.com
//loading the Key file
var certificate = new X509Certificate2(keyFilePath, "notasecret", X509KeyStorageFlags.Exportable);
var credential = new ServiceAccountCredential( new ServiceAccountCredential.Initializer(serviceAccountEmail) {
Scopes = scopes}.FromCertificate(certificate));
create drive service
var service = new DriveService(new BaseClientService.Initializer() {HttpClientInitializer = credential,
ApplicationName = "Drive API Sample",});
You can use files.list to list all of the files on drive.
FilesResource.ListRequest request = service.Files.List();
request.Q = "trashed=false";
title = 'hello'
FileList files = request.Execute();
loop though the items returned find the file you want it is a file resource you can pass it to the following method to down load your file
/// <summary>
/// Download a file
/// Documentation: https://developers.google.com/drive/v2/reference/files/get
/// </summary>
/// <param name="_service">a Valid authenticated DriveService</param>
/// <param name="_fileResource">File resource of the file to download</param>
/// <param name="_saveTo">location of where to save the file including the file name to save it as.</param>
/// <returns></returns>
public static Boolean downloadFile(DriveService _service, File _fileResource, string _saveTo)
{
if (!String.IsNullOrEmpty(_fileResource.DownloadUrl))
{
try
{
var x = _service.HttpClient.GetByteArrayAsync(_fileResource.DownloadUrl );
byte[] arrBytes = x.Result;
System.IO.File.WriteAllBytes(_saveTo, arrBytes);
return true;
}
catch (Exception e)
{
Console.WriteLine("An error occurred: " + e.Message);
return false;
}
}
else
{
// The file doesn't have any content stored on Drive.
return false;
}
}
code ripped from Google drive authentication C#

Web Api - How to detect when a response has finished being sent

In a web api method I am generating a file and then streaming it to the response like so
public async Task<HttpResponseMessage> GetFile() {
FileInfo file = generateFile();
var msg = Request.CreateResponse(HttpStatusCode.OK);
msg.Content = new StreamContent(file.OpenRead());
msg.Content.Headers.ContentType = new MediaTypeHeaderValue("application/pdf");
msg.Content.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment") {FileName = file.Name};
return msg;
}
because this a generated file I want to delete it after the response has finished streaming but I can't seem to find a hook in the pipeline for this.
I suppose that I can put a reference to the file in a static and set up a custom MessageHandler that pulls values out of this same static variable and deletes. However, this seems like it can't possibly be right both because of the use of a static (when this should all be per-request) and because I'd have to register a separate route.
I've seen this question but it seems to not really have much of a useful response.
Nice scenario!...the problem with using message handlers is that response writing happens at the host layers and below message handlers layer, so they are not ideal...
Following is an example of how you could do it:
msg.Content = new CustomStreamContent(generatedFilePath);
public class CustomStreamContent : StreamContent
{
string filePath;
public CustomStreamContent(string filePath)
: this(File.OpenRead(filePath))
{
this.filePath = filePath;
}
private CustomStreamContent(Stream fileStream)
: base(content: fileStream)
{
}
protected override void Dispose(bool disposing)
{
//close the file stream
base.Dispose(disposing);
try
{
File.Delete(this.filePath);
}
catch (Exception ex)
{
//log this exception somewhere so that you know something bad happened
}
}
}
By the way, are you generating this file because you are converting some data into PDF. If yes, then I think you could use PushStreamContent for this purpose by directly writing the converted data into the response stream. This way you need not generate a file first and then worry about deleting it later.
We performed same action in WebAPI. I needed to delete file just after it downloaded form server.
We can create custom response message class. It takes file path as parameter and delete it once its transmitted.
public class FileResponseMessage : HttpResponseMessage
{
private readonly string _filePath;
public FileHttpResponseMessage(string filePath)
{
this._filePath= filePath;
}
protected override void Dispose(bool disposing)
{
base.Dispose(disposing);
Content.Dispose();
File.Delete(_filePath);
}
}
Use this class as below code and it will delete your file once it will be written on response stream.
var response = new FileResponseMessage(filePath);
response.StatusCode = HttpStatusCode.OK;
response.Content = new StreamContent(new FileStream(filePath, FileMode.Open, FileAccess.Read));
response.Content.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment")
{
FileName = "MyReport.pdf"
};
return response;

RESTeasy back-end - Restlet front-end : response entity null

I have some REST services on my server (Jetty, RESTeasy) and a GWT client.
I choosed to use Restlet-GWT module on the front end.
I made a JSE client (RESTeasy client) and my service is well called (i see SQL trace in the log of Jetty server) and i get an xml response.
Then i tried from GWT with Restlet. The web service is called (Jetty log) but i have a null response.
Web service (Back end):
#GET
#Path("/getArt/{id}")
#Produces("application/xml")
public Art getArt(#PathParam("id")int id){
Art art= artDAO.findById(id);
return art;
}
Front-end GWT :
public class Front_End implements EntryPoint {
/**
* This is the entry point method.
*/
public void onModuleLoad() {
final Client client = new Client(Protocol.HTTP);
client.get("http://localhost:8080/rest/service/getArt/1", new Callback() {
#Override
public void onEvent(Request request, Response response) {
System.out.println("Reponse : " + response.getEntity().getText());
}
});
}
RESTeasy client working :
public Object test(int id){
try {
ClientRequest request = new ClientRequest("http://localhost:8080/rest/service/getArt/"+id);
request.accept("application/xml");
ClientResponse<String> response = request.get(String.class);
if (response.getStatus() == 200)
{
Unmarshaller un = jc.createUnmarshaller();
Object o = un.unmarshal(new StringReader(response.getEntity()));
return o;
}
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
Are RESTeasy and Restlet "compatible" ? Should i use Restlet in the back end instead of RESTeasy ? What am i missing ?
Thx in advance
It was a SOP issue.
My server was running on port 8080, and GWT on port 8888.
I used a proxy (put it in your /war in the client side) :
proxy.jsp
<%#page import="javax.naming.Context"%>
<%#page import="javax.naming.InitialContext"%><%#page session="false"%>
<%#page import="java.net.*,java.io.*" %>
<%
try {
String reqUrl = request.getQueryString();
URL url = new URL(reqUrl.substring(4));
HttpURLConnection con = (HttpURLConnection)url.openConnection();
con.setDoOutput(true);
con.setRequestMethod(request.getMethod());
int clength = request.getContentLength();
if (clength > 0) {
con.setDoInput(true);
byte[] idata = new byte[clength];
request.getInputStream().read(idata,0,clength);
con.getOutputStream().write(idata,0,clength);
}
response.setContentType(con.getContentType());
BufferedReader rd = new BufferedReader(new InputStreamReader(con.getInputStream()));
String line;
while ((line = rd.readLine()) != null) {
out.println(line);
}
rd.close();
} catch (Exception e) {
e.printStackTrace();
response.setStatus(500);
}
%>
then in your class where you make the call, your url becomes :
String url ="proxy.jsp?url=" + URL.encode("http://localhost:8080/rest/service/getArt/1");
There is another way to solve it, check https://developers.google.com/web-toolkit/doc/1.6/tutorial/Xsite

Async calls in WP7

I have been experimenting with WP7 apps today and have hit a bit of a wall.
I like to have seperation between the UI and the main app code but Ive hit a wall.
I have succesfully implemented a webclient request and gotten a result, but because the call is async I dont know how to pass this backup to the UI level. I cannot seem to hack in a wait for response to complete or anything.
I must be doing something wrong.
(this is the xbox360Voice library that I have for download on my website: http://www.jamesstuddart.co.uk/Projects/ASP.Net/Xbox_Feeds/ which I am porting to WP7 as a test)
here is the backend code snippet:
internal const string BaseUrlFormat = "http://www.360voice.com/api/gamertag-profile.asp?tag={0}";
internal static string ResponseXml { get; set; }
internal static WebClient Client = new WebClient();
public static XboxGamer? GetGamer(string gamerTag)
{
var url = string.Format(BaseUrlFormat, gamerTag);
var response = GetResponse(url, null, null);
return SerializeResponse(response);
}
internal static XboxGamer? SerializeResponse(string response)
{
if (string.IsNullOrEmpty(response))
{
return null;
}
var tempGamer = new XboxGamer();
var gamer = (XboxGamer)SerializationMethods.Deserialize(tempGamer, response);
return gamer;
}
internal static string GetResponse(string url, string userName, string password)
{
if (!string.IsNullOrEmpty(userName) && !string.IsNullOrEmpty(password))
{
Client.Credentials = new NetworkCredential(userName, password);
}
try
{
Client.DownloadStringCompleted += ClientDownloadStringCompleted;
Client.DownloadStringAsync(new Uri(url));
return ResponseXml;
}
catch (Exception ex)
{
return null;
}
}
internal static void ClientDownloadStringCompleted(object sender, DownloadStringCompletedEventArgs e)
{
if (e.Error == null)
{
ResponseXml = e.Result;
}
}
and this is the front end code:
public void GetGamerDetails()
{
var xboxManager = XboxFactory.GetXboxManager("DarkV1p3r");
var xboxGamer = xboxManager.GetGamer();
if (xboxGamer.HasValue)
{
var profile = xboxGamer.Value.Profile[0];
imgAvatar.Source = new BitmapImage(new Uri(profile.ProfilePictureMiniUrl));
txtUserName.Text = profile.GamerTag;
txtGamerScore.Text = int.Parse(profile.GamerScore).ToString("G 0,000");
txtZone.Text = profile.PlayerZone;
}
else
{
txtUserName.Text = "Failed to load data";
}
}
Now I understand I need to place something in ClientDownloadStringCompleted but I am unsure what.
The problem you have is that as soon as an asynchronous operation is introduced in to the code path the entire code path needs to become asynchronous.
Because GetResponse calls DownloadStringAsync it must become asynchronous, it can't return a string, it can only do that on a callback
Because GetGamer calls GetResponse which is now asynchronous it can't return a XboxGamer, it can only do that on a callback
Because GetGamerDetails calls GetGamer which is now asynchronous it can't continue with its code following the call, it can only do that after it has received a call back from GetGamer.
Because GetGamerDetails is now asynchronous anything call it must also acknowledge this behaviour.
.... this continues all the way up to the top of the chain where a user event will have occured.
Here is some air code that knocks some asynchronicity in to the code.
public static void GetGamer(string gamerTag, Action<XboxGamer?> completed)
{
var url = string.Format(BaseUrlFormat, gamerTag);
var response = GetResponse(url, null, null, (response) =>
{
completed(SerializeResponse(response));
});
}
internal static string GetResponse(string url, string userName, string password, Action<string> completed)
{
WebClient client = new WebClient();
if (!string.IsNullOrEmpty(userName) && !string.IsNullOrEmpty(password))
{
client.Credentials = new NetworkCredential(userName, password);
}
try
{
client.DownloadStringCompleted += (s, args) =>
{
// Messy error handling needed here, out of scope
completed(args.Result);
};
client.DownloadStringAsync(new Uri(url));
}
catch
{
completed(null);
}
}
public void GetGamerDetails()
{
var xboxManager = XboxFactory.GetXboxManager("DarkV1p3r");
xboxManager.GetGamer( (xboxGamer) =>
{
// Need to move to the main UI thread.
Dispatcher.BeginInvoke(new Action<XboxGamer?>(DisplayGamerDetails), xboxGamer);
});
}
void DisplayGamerDetails(XboxGamer? xboxGamer)
{
if (xboxGamer.HasValue)
{
var profile = xboxGamer.Value.Profile[0];
imgAvatar.Source = new BitmapImage(new Uri(profile.ProfilePictureMiniUrl));
txtUserName.Text = profile.GamerTag;
txtGamerScore.Text = int.Parse(profile.GamerScore).ToString("G 0,000");
txtZone.Text = profile.PlayerZone;
}
else
{
txtUserName.Text = "Failed to load data";
}
}
As you can see async programming can get realy messy.
You generally have 2 options. Either you expose your backend code as an async API as well, or you need to wait for the call to complete in GetResponse.
Doing it the async way would mean starting the process one place, then return, and have the UI update when data is available. This is generally the preferred way, since calling a blocking method on the UI thread will make your app seem unresponsive as long as the method is running.
I think the "Silverlight Way" would be to use databinding. Your XboxGamer object should implement the INotifyPropertyChanged interface. When you call GetGamer() it returns immediately with an "empty" XboxGamer object (maybe with GamerTag=="Loading..." or something). In your ClientDownloadStringCompleted handler you should deserialize the returned XML and then fire the INotifyPropertyChanged.PropertyChanged event.
If you look at the "Windows Phone Databound Application" project template in the SDK, the ItemViewModel class is implemented this way.
Here is how you can expose asynchronous features to any type on WP7.

Resources