Cannot delete a file on server using ftp from asp.net - asp.net

I have created an asp.net application to maintain images for a shopping site, it includes 2 functions, one for uploading the image via ftp and the other for deleting the image using ftp.
I can upload files without an issue but when I try to delete a file I get the response "The remote server returned an error: (530) Not logged in."
I'm using the same ftpuri and credentials so I'm a little confused as to why it doesn't work.
Here's the code for the upload which works.
Upload Section :
Dim ftpRequest As FtpWebRequest = CType(WebRequest.Create(ftpuri), FtpWebRequest)
Try
ftpRequest.Method = WebRequestMethods.Ftp.UploadFile
ftpRequest.Credentials = New NetworkCredential(ftpusername, ftppassword)
Dim bytes() As Byte = System.IO.File.ReadAllBytes(filetoupload)
ftpRequest.ContentLength = bytes.Length
Using UploadStream As Stream = ftpRequest.GetRequestStream()
UploadStream.Write(bytes, 0, bytes.Length)
UploadStream.Close()
End Using
Catch ex As Exception
End Try
Here's the code for the delete that fails with the error The remote server returned an error: (530) Not logged in.
Delete Section:
Dim ftpRequest As FtpWebRequest = CType(WebRequest.Create(ftpUri), FtpWebRequest)
Try
ftpRequest.Credentials = New NetworkCredential(ftpusername, ftppassword)
ftpRequest.Method = WebRequestMethods.Ftp.DeleteFile
Dim responseFileDelete As FtpWebResponse = CType(ftpRequest.GetResponse(), FtpWebResponse)
Catch ex As Exception
End Try
In both cases the values in ftpuri, ftpusername and ftppassword are identical.
I can delete the file using ftp software with the same credentials.
Any help would be appreciated.
Ron

Try this way :
public bool DeleteFileFromFtpServer(Uri serverUri, string ftpUsername, string ftpPassword)
{
try
{
// The serverUri should look like this ftp:// scheme.
// It contains server name along with file name that will be deleted.
// eg: ftp://abc.com/test.txt.
if (serverUri.Scheme != Uri.UriSchemeFtp)
{
return false;
}
// Get the object used to communicate with the server.
FtpWebRequest request = (FtpWebRequest)WebRequest.Create(serverUri);
request.Credentials = new NetworkCredential(ftpUsername, ftpPassword);
request.Method = WebRequestMethods.Ftp.DeleteFile;
FtpWebResponse response = (FtpWebResponse)request.GetResponse();
response.Close();
return true;
}
catch (Exception ex)
{
return false;
}
}
Calling:
obj.DeleteFileFromFtpServer(new Uri (toDelFilename), user,pass);

Related

IIS removes "Content-Length" from Header

We use a WebMethod on our IIS Webservice, so that users can download a file.
Our client runs into an exception when connected to one of our customers webservices, because the key "Content-Length" cannot be found in the header (KeyNotFoundException). The method does work for all other customers.
The customer installed a fresh version of Windows Server 2016, one of my colleagues then installed the IIS roles and features. We double and triple checked: the configuration is the same as the one on our internal webservice and as far as we know as on all the webservices other customers run.
After debugging and searching on the internet for the past two days I found out that instead of the "Content-Length" header a header named "Transfer-Encoding" is send, value is "chunked".
It seems that this only occurs when we call the method via POST, but I'm not completely sure about that.
What we have tried so far:
Disabling chunked-encoding with this script: cscript adsutil.vbs set
/W3SVC/AspEnableChunkedEncoding "TRUE"
Disabling chunked-encoding via appcmd: appcmd set config /section:asp /enableChunkedEncoding:False
Setting system.webServer/asp/enableChunkedEncoding to false via the iis configuration manager of the server AND the site.
We restarted the whole machine after each of these steps.
IIS Webmethod Code (shortened):
[WebMethod]
public void Download(string uniqueID)
{
Byte[] data;
var path = GetPath(uniqueID);
data = File.ReadAllBytes(path);
if (data != null)
{
string sExtension = Path.GetExtension(path);
string MimeType = GetMIMEType(sExtension);
HttpContext.Current.Response.ClearContent();
HttpContext.Current.Response.ClearHeaders();
HttpContext.Current.Response.ContentType = "application/octet-stream";
HttpContext.Current.Response.AddHeader("Content-Disposition", "attachment;filename=" + path.Replace(" ", "_"));
HttpContext.Current.Response.AddHeader("Content-Type", MimeType);
HttpContext.Current.Response.AddHeader("Content-Length", data.Length.ToString());
HttpContext.Current.Response.BinaryWrite(data);
HttpContext.Current.Response.Flush();
HttpContext.Current.Response.SuppressContent = true;
HttpContext.Current.ApplicationInstance.CompleteRequest();
}
}
Client Code (shortened, written in Xamarin.Android as an example, same error occurs on iOS)
Stream stream = null;
Java.IO.DataOutputStream dos = null;
var urlConnection = CreateUrlConnection();
urlConnection.DoInput = true; // Allow Inputs
urlConnection.DoOutput = true; // Allow Outputs
urlConnection.RequestMethod = "POST";
urlConnection.SetRequestProperty("Content-Type", "application/x-www-form-urlencoded");
dos = new Java.IO.DataOutputStream(urlConnection.OutputStream);
string encodedParameters = "";
bool first = true;
foreach (Parameter param in parameters)
{
if (first)
first = false;
else
encodedParameters += "&";
encodedParameters += HttpUtility.UrlEncode(param.Name);
encodedParameters += "=";
encodedParameters += HttpUtility.UrlEncode(param.Value);
}
dos.WriteBytes(encodedParameters);
dos.Flush();
dos.Close();
stream = urlConnection.InputStream;
var header = urlConnection.HeaderFields;
var bytesToRead = int.Parse(header["Content-Length"][0]); // Exception gets thrown here

Async await to save file causes "Process cannot access file because it is being used by another process" error

I have the following code to save an excel file on the server and then read its content:
if (file.Length > 0)
{
string path = _hostingEnvironment.ContentRootPath + "/CSV-import-students/";
FileStream fs = new FileStream(Path.Combine(path, file.FileName), FileMode.Create);
await file.CopyToAsync(fs);
FileInfo fileUploaded = new FileInfo(Path.Combine(path, file.FileName));
using (ExcelPackage package = new ExcelPackage(fileUploaded))
{
StringBuilder sb = new StringBuilder();
ExcelWorksheet worksheet = package.Workbook.Worksheets[0];
int rowCount = worksheet.Dimension.Rows;
int ColCount = worksheet.Dimension.Columns;
bool bHeaderRow = true;
}
The file is saved fine on the server. But, then when I try to access it, I receive "Process cannot access file because it is being used by another process" error. How can I prevent this error? Any ideas?
Almost invariably, when newing up a class that implements IDisposable (such as FileStream), you should do so with a using statement:
using (var fs = new FileStream(Path.Combine(path, file.FileName), FileMode.Create))
{
await file.CopyToAsync(fs);
}
This will automatically dispose of the resource when the using statement goes out of scope, and in the case of FileStream, will flush the write and close the file. That's the source of your issue, so this will solve your problem.
However, you might also need to contend with concurrency. It's possible for two requests to be processed simultaneously that both need to work with the same file. You should plan for concurrency, by catching file access violation exceptions and responding via a retry policy. The Polly exception handling library can help here.

Corresponding web api function to accept file

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

Asp.Net application with DropBox not working

I set the DropBox application type Full DropBox; I set on my application the following function:
Private Const AppKey As String = "my key"
Private Const AppSecret As String = "my secret"
Private Function Upload() As String
Dim client As DropNetClient
Dim token As UserLogin
Dim userToken As String = My.Settings.userToken
Dim userSecret As String = My.Settings.userSecret
Dim needAccessToken As Boolean = (String.IsNullOrEmpty(userToken) Or String.IsNullOrEmpty(userSecret))
If (needAccessToken) Then
client = New DropNet.DropNetClient(AppKey, AppSecret)
client.UseSandbox = True
client.GetToken()
Dim url = client.BuildAuthorizeUrl()
Try
token = client.GetAccessToken()
Catch ex As Exception
Console.WriteLine("Exception! " + ex.Message)
Exit Function
End Try
userToken = token.Token
userSecret = token.Secret
My.Settings.Properties.Item("userToken").DefaultValue = userToken
My.Settings.Properties.Item("userSecret").DefaultValue = userSecret
My.Settings.Save()
Else
client = New DropNet.DropNetClient(AppKey, AppSecret, userToken, userSecret)
client.UseSandbox = True
End If
Dim rawData As Byte() = File.ReadAllBytes(Server.MapPath("") + "/Fax/" + "Fax.zip")
Dim result As MetaData = client.UploadFile("/", "fax.zip", rawData)
End Function
Unfortunately education tokens = GetAccessToken () I get the error:
Received Response [Unauthorized]: Expected to see [OK]. The HTTP response was [{" "error" ":" "Request token has not been properly authorized by a user. ""}] ".
I checked the URL (client.BuildAuthorizedUrl ()) and returns me "Unauthorized".
How can I link to Dropbox folder? I do something wrong? Or do I need to set better application of Dropbox?
Once you get the URL via BuildAuthorizeUrl, you need to send the user to that address and have them authorize your app. Only once they've done that can you call GetAccessToken.
The error you're seeing is because you're trying to get the access token before the user has actually authorized your app.

Apache Abdera Multipart Request throwing nullpointer Exception(IBM connection API)

I am using Apache abdera to post multipart request to IBM connection 4.0 API. I am getting nullpointer exception from Abdera API. Please let me know what's the root cause.
private void createEntryWithAttachment(){
try {
String activityId = "urn:lsid:ibm.com:oa:662d0dc7-0308-48ee-8291-d730c733d2d1";
String activityIdLocal = activityId.substring(activityId.lastIndexOf(":")+1, activityId.length());
String createEntryLocal = createEntry+activityIdLocal;
Abdera abdera = new Abdera();
AbderaClient client = new AbderaClient(abdera);
AbderaClient.registerTrustManager();
System.out.println("pd --->"+pd);
client.addCookie("poktam2cl.iespc.ibm.com", "PD-S-SESSION-ID", pd, "/", null, true);
RequestOptions requestOptions = client.getDefaultRequestOptions();
requestOptions.setUseChunked(true);
requestOptions.setHeader("Connection", "close");
requestOptions.setHeader("Content-Type", "multipart/related;type=\"application/atom+xml\"");
requestOptions.setContentType("multipart/related;type=\"application/atom+xml\"");
requestOptions.setSlug("Sample.txt");
Credentials credentials = new UsernamePasswordCredentials(username, password);
client.addCredentials(createEntryLocal, AuthScope.ANY_REALM,AuthScope.ANY_SCHEME, credentials);
Entry entry = abdera.getFactory().newEntry();
entry.setTitle("create entry with attachment title ");
entry.setContent("create entry with attachment content");
javax.xml.namespace.QName field = new QName("http://www.ibm.com/xmlns/prod/sn", "field", "snx");
org.apache.abdera.model.Element fieldElement = entry.addExtension(field);
fieldElement.setAttributeValue("type", "file");
fieldElement.setAttributeValue("name", "sampletextfile1");
fieldElement.setAttributeValue("position", "3000");
FileInputStream fis = new FileInputStream(filepath);
requestOptions.setHeader("Content-Length", "35");
entry.addCategory("http://www.ibm.com/xmlns/prod/sn/type","entry", "Entry");
ClientResponse response = client.post(createEntryLocal, entry, fis, "multipart/related;type=\"application/atom+xml\"", requestOptions );
System.out.println("Entry Created with attachment's resp: " + response.getStatus());
if(response.getStatus() == 201){
System.out.println("Entry Created with attachment successfully .....");
printIBMConnectionErrorMessage(response);
}else{
System.out.println("Entry with attachment creation failed");
printIBMConnectionErrorMessage(response);
//System.exit(0);
}
} catch (Exception e) {
e.printStackTrace();
}
}
Output
java.lang.NullPointerException
at org.apache.abdera.protocol.client.util.MultipartRelatedRequestEntity.writeInput(MultipartRelatedRequestEntity.java:74)
at org.apache.abdera.protocol.client.util.MultipartRelatedRequestEntity.writeRequest(MultipartRelatedRequestEntity.java:59)
at org.apache.commons.httpclient.methods.EntityEnclosingMethod.writeRequestBody(EntityEnclosingMethod.java:499)
at org.apache.commons.httpclient.HttpMethodBase.writeRequest(HttpMethodBase.java:2114)
at org.apache.commons.httpclient.HttpMethodBase.execute(HttpMethodBase.java:1096)
at org.apache.commons.httpclient.HttpMethodDirector.executeWithRetry(HttpMethodDirector.java:398)
at org.apache.commons.httpclient.HttpMethodDirector.executeMethod(HttpMethodDirector.java:171)
at org.apache.commons.httpclient.HttpClient.executeMethod(HttpClient.java:397)
at org.apache.commons.httpclient.HttpClient.executeMethod(HttpClient.java:323)
at org.apache.abdera.protocol.client.AbderaClient.execute(AbderaClient.java:688)
at org.apache.abdera.protocol.client.AbderaClient.post(AbderaClient.java:306)
at JavaAgentEntryWithAttachment.createEntryWithAttachment(JavaAgentEntryWithAttachment.java:157)
at JavaAgentEntryWithAttachment.main(JavaAgentEntryWithAttachment.java:66)
This exception is coming from abdera API, class called MultipartRelatedRequestEntity.java, Line no 74. I have placed line no 74 source code below. So its clear that contentSrc is null & Abdera API not allowing me to set this value. Please let me know what I am missing here.
String contentId = entry.getContentSrc().toString();
I did in two steps:
Send the file
Call to update the data
Each with the good mime type. You can not send the file with XML mime type. And put the length of the file.
It is possible to avoid the nullpointer and do it in one request. I had the same issue and created another issue and managed to find a solution. You can find it here.
It comes down to the following code example where you create a HttpClient Part which can contain a StringPart and a FilePart
final Entry entry = // ... Create your Entry
final RequestOptions options = this.client.getDefaultRequestOptions();
options.setHeader("Content-Type", "multipart/related;type=\"application/atom+xml\"");
StringPart entryPart = new StringPart("entry", entry.toString());
entryPart.setContentType("application/atom+xml");
FilePart filePart = new FilePart("file", new File(resource.getFile()));
RequestEntity request = new MultipartRequestEntity(new Part[] { entryPart, filePart}, this.client.getHttpClientParams());
ClientResponse response = client.post(this.url + this.activityId, request, options);
Hope this will help people in the future if they are using Abdera.

Resources