I've been looking at file transfer tutorials for windows phone 8, but for some reason they all seem quite code extensive for what i want, wich is simply to download a file(image in this case) to the phone and use the path its been saved too as a source of a control
i get the following Json from a webservice
[{"name":"image1.png","link":"http://www.xxxxxx.com/image1.png"},{"name":"image2.png","link":"http://www.xxxxxx.com/image1.jpg"}]
and want to use those links to do the downloads
in sum i want to
Check if file exists, if not download, and get its path to use later.
First you need to parse the JSON, I would recommend Newtonsoft JSON for that.
After that you need to check if file exists. (You could use the MD5 of the URL as the filename for localstorage and check if there is a file with the name)
If the file does not exist you need to use a HttpWebRequest to download the file and then save it to the isolated storage.
EDIT:
To check if file exists:
IsolatedStorageFile localStorage = IsolatedStorageFile.GetUserStoreForApplication();
if(localStorage.FileExists("image1.png"))
//use cached version
WebRequest:
WebRequest req = HttpWebRequest.Create("http://domain.com/image.png");
WebResponse res = await GetResponseAsync(req);
if (res != null)
{
Stream rspStream = res.GetResponseStream();
//save stream to isolated storage
}
GetResponseAsync:
private static Task<HttpWebResponse> GetResponseAsync(WebRequest request)
{
var taskComplete = new TaskCompletionSource<HttpWebResponse>();
request.BeginGetResponse(asyncResponse =>
{
try
{
HttpWebRequest responseRequest = (HttpWebRequest)asyncResponse.AsyncState;
HttpWebResponse someResponse = (HttpWebResponse)responseRequest.EndGetResponse(asyncResponse);
taskComplete.TrySetResult(someResponse);
}
catch (WebException webExc)
{
HttpWebResponse failedResponse = (HttpWebResponse)webExc.Response;
taskComplete.TrySetResult(failedResponse);
}
}, request);
return taskComplete.Task;
}
Related
I recently developed a .NET Web App that downloaded zip files from a certain, set location on our network. I did this by retrieving the content stream and then passing it back to the View by returning the File().
Code from the .NET Web App who's behavior I want to emulate:
public async Task<ActionResult> Download()
{
try
{
HttpContent content = plan.response.Content;
var contentStream = await content.ReadAsStreamAsync(); // get the actual content stream
if (plan.contentType.StartsWith("image") || plan.contentType.Contains("pdf"))
return File(contentStream, plan.contentType);
return File(contentStream, plan.contentType, plan.PlanFileName);
}
catch (Exception e)
{
return Json(new { success = false });
}
}
plan.response is constructed in a separate method then stored as a Session variable so that it is specific to the user then accessed here for download.
I am now working on a Windows Forms Application that needs to be able to access and download these files from the same location. I am able to retrieve the response content, but I do not know how to proceed in order to download the zip within a Windows Forms Application.
Is there a way, from receiving the content stream, that I can download this file using a similar method within a Windows Form App? It would be convenient as accessing the files initially requires logging in and authenticating the user and thus can not be accessed normally with just a filepath.
Well, depending on what you're trying to accomplish, here's a pretty simplistic example of download a file from a URL and saving it locally:
string href = "https://www.learningcontainer.com/wp-content/uploads/2020/05/sample-zip-file.zip";
WebRequest request = WebRequest.Create(href);
using (WebResponse response = request.GetResponse())
{
using (Stream dataStream = response.GetResponseStream())
{
Uri uri = new Uri(href);
string fileName = Path.GetTempPath() + Path.GetFileName(uri.LocalPath);
using (FileStream fs = new FileStream(fileName, FileMode.OpenOrCreate))
{
dataStream.CopyTo(fs);
}
}
}
Im trying to create a web service which gets to a URL e.g. www.domain.co.uk/prices.csv and then reads the csv file. Is this possible and how? Ideally without downloading the csv file?
You could use:
public string GetCSV(string url)
{
HttpWebRequest req = (HttpWebRequest)WebRequest.Create(url);
HttpWebResponse resp = (HttpWebResponse)req.GetResponse();
StreamReader sr = new StreamReader(resp.GetResponseStream());
string results = sr.ReadToEnd();
sr.Close();
return results;
}
And then to split it:
public static void SplitCSV()
{
List<string> splitted = new List<string>();
string fileList = getCSV("http://www.google.com");
string[] tempStr;
tempStr = fileList.Split(',');
foreach (string item in tempStr)
{
if (!string.IsNullOrWhiteSpace(item))
{
splitted.Add(item);
}
}
}
Though there are plenty of CSV parsers out there and i would advise against rolling your own. FileHelpers is a good one.
// Download the file to a specified path. Using the WebClient class we can download
// files directly from a provided url, like in this case.
System.Net.WebClient client = new WebClient();
client.DownloadFile(url, csvPath);
Where the url is your site with the csv file and the csvPath is where you want the actual file to go.
In your Web Service you could use the WebClient class to download the file, something like this ( I have not put any exception handling, not any using or Close/Dispose calls, just wanted to give the idea you can use and refine/improve... )
using System.Net;
WebClient webClient = new WebClient();
webClient.DownloadFile("http://www.domain.co.uk/prices.csv");
then you can do anything you like with it once the file content is available in the execution flow of your service.
if you have to return it to the client as return value of the web service call you can either return a DataSet or any other data structure you prefer.
Sebastien Lorion's CSV Reader has a constructor that takes a Stream.
If you decided to use this, your example would become:
void GetCSVFromRemoteUrl(string url)
{
HttpWebRequest request = WebRequest.Create(url) as HttpWebRequest;
HttpWebResponse response = request.GetResponse() as HttpWebResponse;
using (CsvReader csvReader = new CsvReader(response.GetResponseStream(), true))
{
int fieldCount = csvReader.FieldCount;
string[] headers = csvReader.GetFieldHeaders();
while (csvReader.ReadNextRecord())
{
//Do work with CSV file data here
}
}
}
The ever popular FileHelpers also allows you to read directly from a stream.
The documentation for WebRequest has an example that uses streams. Using a stream allows you to parse the document without storing it all in memory
I am trying to create my own download manger.
When a link is added to the download manger I use a webclient to get it's information from the server. Like so
WebClient webClient = new WebClient();
webClient.OpenRead(link);
string filename = webClient.ResponseHeaders["Content-Disposition"];
After that I download the file using DownloadFile
FileInfo fileInfo = new FileInfo(path);
if (!fileInfo.Exists)
{
webClient.DownloadFile(link, path);
}
When I do it like this. I get a WebException timeout.
However, when I remove the webClient.ResponseHeaders part. It never get the timeout exception.
I really need to read the Content-Disposition because some of the links don't have the name of the file on them.
I even tried using a different webclient for downloading and getting it's info but I got the same result.
I was able to fix the problem by finding another way to get the files info.
string Name = "";
HttpWebRequest myHttpWebRequest = (HttpWebRequest)WebRequest.Create(Link);
HttpWebResponse myHttpWebResponse = (HttpWebResponse)myHttpWebRequest.GetResponse();
for(int i=0; i < myHttpWebResponse.Headers.Count; i++)
{
if (myHttpWebResponse.Headers.Keys[i] == "Content-Disposition")
{
Name = myHttpWebResponse.Headers[i];
}
}
myHttpWebResponse.Close();
I have written a procedure that will open a xls from a local disc, refresh the data in it and then save it again. This works fine.
The problem occurs when I replace the filename to point to a SharePoint site. It opens the file fine. Refreshes the file, but when it trys to save the file it throws an exception with the message "Cannot save as that name. Document was opened as read-only.".
If I try and save the file with a different filename then it works fine.
Does anybody know what I am missing? I think it must have somethoing to do with how I am opening the file. Is there another way that I can force the opening of the file in a read/write manner?
private static void RefreshExcelDocument(string filename)
{
var xls = new Microsoft.Office.Interop.Excel.Application();
xls.Visible = true;
xls.DisplayAlerts = false;
var workbook = xls.Workbooks.Open(Filename: filename, IgnoreReadOnlyRecommended: true, ReadOnly: false);
try
{
// Refresh the data from data connections
workbook.RefreshAll();
// Wait for the refresh occurs - *wish there was a better way than this.
System.Threading.Thread.Sleep(5000);
// Save the workbook back again
workbook.SaveAs(Filename: filename); // This is when the Exception is thrown
// Close the workbook
workbook.Close(SaveChanges: false);
}
catch (Exception ex)
{
//Exception message is "Cannot save as that name. Document was opened as read-only."
}
finally
{
xls.Application.Quit();
xls = null;
}
}
Many thanks in advance for suggestions.
Jonathan
Unfortunately you can't save directly to SharePoint using the Excel API. That's why the file is being opened as read only - it's not allowed.
The good news is that it is possible, but you have to submit the form via a web request. Even better news is that there is sample code on MSDN! In particular notice the PublishWorkbook method that sends a local copy of the Excel file to the server via a web request:
static void PublishWorkbook(string LocalPath, string SharePointPath)
{
WebResponse response = null;
try
{
// Create a PUT Web request to upload the file.
WebRequest request = WebRequest.Create(SharePointPath);
request.Credentials = CredentialCache.DefaultCredentials;
request.Method = "PUT";
// Allocate a 1K buffer to transfer the file contents.
// The buffer size can be adjusted as needed depending on
// the number and size of files being uploaded.
byte[] buffer = new byte[1024];
// Write the contents of the local file to the
// request stream.
using (Stream stream = request.GetRequestStream())
using (FileStream fsWorkbook = File.Open(LocalPath,
FileMode.Open, FileAccess.Read))
{
int i = fsWorkbook.Read(buffer, 0, buffer.Length);
while (i > 0)
{
stream.Write(buffer, 0, i);
i = fsWorkbook.Read(buffer, 0, buffer.Length);
}
}
// Make the PUT request.
response = request.GetResponse();
}
finally
{
response.Close();
}
}
The sample code describes a scenario for the 2007 versions of these products but other versions should behave in the same way.
What does the filename of a failed example looks like? Aren't documents used in SharePoint stored in the database? Or am I getting your problem wrong? Otherwise I could imagine that the file you are trying to store is write protected by the operation system and cannot be modified.
In my application I use the WebClient class to download files from a Webserver by simply calling the DownloadFile method. Now I need to check whether a certain file exists prior to downloading it (or in case I just want to make sure that it exists). I've got two questions with that:
What is the best way to check whether a file exists on a server without transfering to much data across the wire? (It's quite a huge number of files I need to check)
Is there a way to get the size of a given remote file without downloading it?
Thanks in advance!
WebClient is fairly limited; if you switch to using WebRequest, then you gain the ability to send an HTTP HEAD request. When you issue the request, you should either get an error (if the file is missing), or a WebResponse with a valid ContentLength property.
Edit: Example code:
WebRequest request = WebRequest.Create(new Uri("http://www.example.com/"));
request.Method = "HEAD";
using(WebResponse response = request.GetResponse()) {
Console.WriteLine("{0} {1}", response.ContentLength, response.ContentType);
}
When you request file using the WebClient Class, the 404 Error (File Not Found) will lead to an exception. Best way is to handle that exception and use a flag which can be set to see if the file exists or not.
The example code goes as follows:
System.Net.HttpWebRequest request = null;
System.Net.HttpWebResponse response = null;
request = (System.Net.HttpWebRequest)System.Net.HttpWebRequest.Create("www.example.com/somepath");
request.Timeout = 30000;
try
{
response = (System.Net.HttpWebResponse)request.GetResponse();
flag = 1;
}
catch
{
flag = -1;
}
if (flag==1)
{
Console.WriteLine("File Found!!!");
}
else
{
Console.WriteLine("File Not Found!!!");
}
You can put your code in respective if blocks.
Hope it helps!
What is the best way to check whether a file exists on a server
without transfering to much data across the wire?
You can test with WebClient.OpenRead to open the file stream without reading all the file bytes:
using (var client = new WebClient())
{
Stream stream = client.OpenRead(url);
// ^ throws System.Net.WebException: 'Could not find file...' if file is not present
stream.Close();
}
This will indicate if the file exists at the remote location or not.
To fully read the file stream, you would do:
using (var client = new WebClient())
{
Stream stream = client.OpenRead(url);
StreamReader sr = new StreamReader(stream);
Console.WriteLine(sr.ReadToEnd());
stream.Close();
}
In case anyone stuck with ssl certificate issue
ServicePointManager.ServerCertificateValidationCallback = new RemoteCertificateValidationCallback
(
delegate { return true; }
);
WebRequest request = WebRequest.Create(new Uri("http://.com/flower.zip"));
request.Method = "HEAD";
using (WebResponse response = request.GetResponse())
{
Console.WriteLine("{0} {1}", response.ContentLength, response.ContentType);
}