FTP Client ul/dl in Universal Windows app - c#

I'm struggling with uploading and downloading files to a FTP server in UWP/Windows Store apps.
The FtpWebRequest Class is missing so you have to use your own Ftp Client. I haven't found any working open-source libraries for this yet. I tried Windows 8.1 Sockets: Ftp Client Sample with Sockets in C#/Xaml; The directory listing works fine but the up/download breaks after a few bytes. Maybe a buffer issue? This is the upload stream, the download function is on the msdn site.
using (var stream = await ftpClient.OpenWriteAsync(newFilePath))
{
var bytes = System.Text.Encoding.UTF8.GetBytes(filecontent);
await stream.WriteAsync(bytes.AsBuffer());
await stream.FlushAsync();
}
or
using (var stream = await OpenWriteAsync(destination))
{
// A more efficient way, maybe a DataReader can be used here
using (var readStream = await file.OpenReadAsync())
{
var buffer = new byte[512].AsBuffer();
var resultingBuffer = new byte[0];
while (true)
{
IBuffer readBuffer = await readStream.ReadAsync(buffer, 512, InputStreamOptions.Partial);
if (readBuffer.Length == 0) break;
resultingBuffer = resultingBuffer.Concat(readBuffer.ToArray()).ToArray();
}
await stream.WriteAsync(resultingBuffer.AsBuffer());
await stream.FlushAsync();
}
}
I read that the FTP upload is not supported by the BackgroundTransfer class. Has someone found a solution for loading files to a password-protected FTP server in UWP apps?
Thanks for your help!

Related

C# Server downloads the file and transfers it to the user at the same time. Download fails [Google Drive]

I'm writing a program with ASP.NET Core.
The program will download the file from Google Drive without storing it in Memory or disk and transfer it to the user.
Download function in Google Drive official libraries does not continue until the download has finished. For this reason, I send a normal GET request to the API and read the file as a stream and return to the user.
But after a certain size, downloading in programs like IDM or browser results in an error.
In short, I want to make a program that uses the server as a bridge, and it should not be interrupted.
[HttpGet]
[DisableRequestSizeLimit]
public async Task<FileStreamResult> Download([FromQuery(Name = "file")] string fileid)
{
if (!string.IsNullOrEmpty(fileid))
{
var decoded = Base64.Base64Decode(fileid);
var file = DriveAPI.service.Files.Get(decoded);
file.SupportsAllDrives = true;
file.SupportsTeamDrives = true;
var fileinf = file.Execute();
var filesize = fileinf.FileSize;
var cli = new HttpClient(DriveAPI.service.HttpClient.MessageHandler);
//var req = await cli.SendAsync(file.CreateRequest());
var req = await cli.GetAsync($"https://www.googleapis.com/drive/v2/files/{decoded}?alt=media", HttpCompletionOption.ResponseHeadersRead);
//var req = await DriveAPI.service.HttpClient.GetAsync($"https://www.googleapis.com/drive/v2/files/{decoded}?alt=media", HttpCompletionOption.ResponseHeadersRead);
var contenttype = req.Content.Headers.ContentType.MediaType;
if (contenttype == "application/json")
{
var message = JObject.Parse(req.Content.ReadAsStringAsync().Result).SelectToken("error.message");
if (message.ToString() == "The download quota for this file has been exceeded")
{
throw new Exception("Google Drive Günlük İndirme Kotası Aşıldı. Lütfen 24-48 Saat Sonra Tekrar Deneyin.");
}
else
{
throw new Exception(message.ToString());
}
}
else
{
return File(req.Content.ReadAsStream(), contenttype, fileinf.OriginalFilename, false);
}
}
else
{
return null;
}
}
Some errors are written to the log file when downloading:
Received an unexpected EOF or 0 bytes from the transport stream.
Unable to read data from the transport connection.
etc.
If user is using IDM, the error is:
Server sent wrong answer on restart command
If user is downloading from browser, the error is:
Network Error
I started a 1.5Gb file download with 8 mbps internet when approximate download size is 900Mb, IDM stopped download with said error.
I have no idea other than returning FileStreamResult in ASP.NET Core - how to download concurrent files?

Set stream for MediaElement from Http request

I have a code for recording some music/video file from online stream (video stream or radio).
How can I modify it for setting the SetSource property to my MediaElement (from IBuffer or Bytes[],... for example)?
(I cannot use the variant like this:
mediaElement1.Source = new Uri(urlLinkToOnlineStream);
mediaElement1.Play();
)
I need to set SetSource directly from already opened stream (I need write to file and record the same bytes[] from stream in the same moment or with a small pause).
HttpClientHandler aHandler = new HttpClientHandler();
aHandler.ClientCertificateOptions = ClientCertificateOption.Automatic;
HttpClient aClient = new HttpClient(aHandler);
aClient.DefaultRequestHeaders.ExpectContinue = false;
HttpResponseMessage response = await aClient.GetAsync(urlLinkToOnlineStream, HttpCompletionOption.ResponseHeadersRead);
var destinationFile = await KnownFolders.MusicLibrary.CreateFileAsync(#"recorded.mp3", CreationCollisionOption.ReplaceExisting);
var fileStream = await destinationFile.OpenAsync(FileAccessMode.ReadWrite);
Stream stream = await response.Content.ReadAsStreamAsync();
IInputStream inputStream = stream.AsInputStream();
ulong totalBytesRead = 0;
while (true)
{
// Read from the web.
IBuffer buffer = new Windows.Storage.Streams.Buffer(1024);
buffer = await inputStream.ReadAsync(buffer, buffer.Capacity, InputStreamOptions.None);
if (buffer.Length == 0)
{
break;
}
totalBytesRead += buffer.Length;
await fileStream.WriteAsync(buffer);
}
inputStream.Dispose();
fs.Dispose();
Are you developing the Universal Windows Platform App or Windows Phone 8.1 App? The UWP supports the media stream protocol like HTTP Live Stream. You can assign the URL to the media element directly.
UWP:
media.Source = new Uri("http://amssamples.streaming.mediaservices.windows.net/49b57c87-f5f3-48b3-ba22-c55cfdffa9cb/Sintel.ism/manifest(format=m3u8-aapl)");
For Windows Phone 8.1, you can use the open source stream media library.
For example: Windows Phone Streaming Media
I know this is old, however I have a working example for a single audio file that can be adapted for a stream.
InMemoryRandomAccessStream stream = new InMemoryRandomAccessStream();
HttpClient hc = new HttpClient();
HttpResponseMessage msg = await hc.GetAsync(urlLinkToOnlineStream);
await RandomAccessStream.CopyAsync(await msg.Content.ReadAsInputStreamAsync(), stream);
stream.Seek(0);
myMediaElement.SetSource(stream, msg.Content.Headers.ContentType.ToString());
You must remember to call Dispose() on your InMemoryRandomAccessStream and HttpClient when you are sure you have finished with them. Otherwise you will most likely end up with a memory leak.
I'm not entirely sure how you intend to do the buffering, but you if you call Dispose() on the stream (in my example) playback will fail. It will also start playing the new chunk of data if you call SetSource before current chunk has finished.

C# Downloading And Using File Causes System.UnauthorizedAccessException

i'm trying to create an app that downloads a file and then edits this file.
The Problem Im having is once the file is downloaded it doesn't seem to let go of that file, i can download the file to its local storage, i have gotten the file manually from the Iso and its fine. if i use the app to proceed after downloading the file i get the System.UnauthorizedAccessException error, but if i close and open the app and then just edit the file saved in iso it works, like i said its like something is still using the downloaded file.
public async void DownloadTrack(Uri SongUri)
{
var httpClient = new HttpClient();
var data = await httpClient.GetByteArrayAsync(SongUri);
var file = await ApplicationData.Current.LocalFolder.CreateFileAsync("Test.mp3", CreationCollisionOption.ReplaceExisting);
var targetStream = await file.OpenAsync(FileAccessMode.ReadWrite);
await targetStream.AsStreamForWrite().WriteAsync(data, 0, data.Length);
await targetStream.FlushAsync();
}
this code works fine to download the mp3, as ive tested the download file. I have seen if examples where the code ends with
targetStream.Close();
but it doesnt give me that, is there another way to close the download
thanks.
Instead of calling Close() or Dispose() I really like to use using which does the job automatically. So your method could look like this:
public async void DownloadTrack(Uri SongUri)
{
using (HttpClient httpClient = new HttpClient())
{
var data = await httpClient.GetByteArrayAsync(SongUri);
var file = await ApplicationData.Current.LocalFolder.CreateFileAsync("Test.mp3", CreationCollisionOption.ReplaceExisting);
using (var targetStream = await file.OpenAsync(FileAccessMode.ReadWrite))
{
await targetStream.AsStreamForWrite().WriteAsync(data, 0, data.Length);
await targetStream.FlushAsync();
}
}
}

Copy or open external file in windows RT app

I would like to show a pdf from a website in my windows rt app (for Desktops with windows 8). How can I handle this?
If I add the file manually to the asset I can display it. But how can I do this with files where are not located on my asset Folder?
Can I copy the file to the StorageFolder?
Or can I directly open the file from the website?
Please give me some hints how I can solve this.
THX
To open files from you application you use Launcher in Windows 8 Applications. Refer the MSDN LINK: http://msdn.microsoft.com/en-in/library/windows/apps/hh701465.aspx and http://www.codeguru.com/win_mobile/win_store_apps/launching-files-with-associated-programs-in-windows-8.x-and-vb.htm
Hi I want to open it in my app and I not want to use the launcher.
I copy the file with HttpWebRequest to LocalFolder and process the pdf. I've solved it this way:
StorageFolder localFolder = Windows.Storage.ApplicationData.Current.LocalFolder;
StorageFile file = null;
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(filepath);
//TODO Systemuser
request.Credentials = System.Net.CredentialCache.DefaultNetworkCredentials;
var response = await request.GetResponseAsync();
List<Byte> allBytes = new List<byte>();
using (Stream imageStream = response.GetResponseStream()) {
byte[] buffer = new byte[4000];
int bytesRead = 0;
while ((bytesRead = await imageStream.ReadAsync(buffer, 0, 4000)) > 0) {
allBytes.AddRange(buffer.Take(bytesRead));
}
}
file = await localFolder.CreateFileAsync(fileName, CreationCollisionOption.ReplaceExisting);
await FileIO.WriteBytesAsync(file, allBytes.ToArray());
await RenderPDFPage(fileName);

When I use the .NET WebClient DownloadFileAsync I randomly get zero length files returned

I'm trying to download files from my FTP server - multiples at the same time. When i use the DownloadFileAsync .. random files are returned with a byte[] Length of 0. I can 100% confirm the file exists on the server and has content AND there FTP server (running Filezilla Server) isn't erroring and say's the file has been transferred.
private async Task<IList<FtpDataResult>> DownloadFileAsync(FtpFileName ftpFileName)
{
var address = new Uri(string.Format("ftp://{0}{1}", _server, ftpFileName.FullName));
var webClient = new WebClient
{
Credentials = new NetworkCredential(_username, _password)
};
var bytes = await webClient.DownloadDataTaskAsync(address);
using (var stream = new MemoryStream(bytes))
{
// extract the stream data (either files in a zip OR a file);
return result;
}
}
When I try this code, it's slower (of course) but all the files have content.
private async Task<IList<FtpDataResult>> DownloadFileAsync(FtpFileName ftpFileName)
{
var address = new Uri(string.Format("ftp://{0}{1}", _server, ftpFileName.FullName));
var webClient = new WebClient
{
Credentials = new NetworkCredential(_username, _password)
};
// NOTICE: I've removed the AWAIT and a different method.
var bytes = webClient.DownloadData(address);
using (var stream = new MemoryStream(bytes))
{
// extract the stream data (either files in a zip OR a file);
return result;
}
}
Can anyone see what I'm doing wrong, please? Why would the DownloadFileAsync be randomly returning zero bytes?
Try out FtpWebRequest/FtpWebResponse classes. You have more available to you for debugging purposes.
FtpWebRequest - http://msdn.microsoft.com/en-us/library/system.net.ftpwebrequest(v=vs.110).aspx
FtpWebResponse - http://msdn.microsoft.com/en-us/library/system.net.ftpwebresponse(v=vs.110).aspx
Take a look at http://netftp.codeplex.com/. It appears as though almost all methods implement IAsyncResult. There isn't much documentation on how to get started, but I would assume that it is similar to the synchronous FTP classes from the .NET framework. You can install the nuget package here: https://www.nuget.org/packages/System.Net.FtpClient/

Categories