How to download a file without extension in C# - c#

Okay so I want to download a file from a website, but the file is lacking an extension.
(it's an image file, I know this much, but the link does not provide the actual extension)
When I use webrequest, or webclient to download the file I get a "404 file not found" exception.
WebClient wc = new WebClient();
Stream strm = wc.DownloadFile("http://some_site.some_domain/some_image.","C:/some_directory/save_name.some_extention");
Notice the lack of extention at the end of the URL.
The site in question displays the image fine in a webbrowser, but when viewing just the image there is no extension and thus it's treated an unknown file (not showing an image).
So simply put: how do I download a file if there is no extention specified?
Thanks in advance!

So you're trying to determine what extension to give the file after downloading? If the URL doesn't have one you would have to inspect the actual data of the file.
You might be able to inspect the beginning of the file and see if it matches known valid file types. For instance, PNGs seem to have 'PNG' as bytes 2-4 (at least in the ones I've inspected). By looking at that data you should be able to determine the format with a fairly high accuracy.

This would be my best suggestion, if this doesn't work I don't know how to solve you problem...
List<string> fileExtensions = new List<string>(){"png","gif","bmp","jpg"}// other known image file extensions here...
WebClient wc = new WebClient();
foreach(var extension in fileExtensions)
{
try
{ wc.DownloadFile("http://some_site.some_domain/some_image."+extension,"C:/some_directory/save_name."+extension);
break;
}
catch {}
}
This would just be a work around, I guess... Not a real solution...

Related

InsertInlineImage or ReplaceImage URI

I'm writing a WinForms application. I created a Google Doc template file that contains placeholders like {{name}} for various text elements. I can successfully make a copy of this document and use the BatchUpdateDocumentRequest to modify them just fine.
However, I also have an embedded image in the document. I can obtain the objectId for this image just fine. I either want to replace this image with another or remove it from my template and then append my new image to the end of the document. In both cases, the InsertInlineImage or ReplaceImage classes require a URI of the image to insert or replace with. This is where I have an issue.
The image itself has been captured from a control on the WinForms. Its actually a chart. I've saved the image in PNG format since I know that is one of the formats supported by Google drive/docs. I figured in order to use it in the batch update, I would need to upload it first, so I did and got its file id and webcontentlink back in the response.
I'm not locked into any particular way of doing this. I originally tried creating an HTML file, uploading but then it would strip the image from it, so became useless, so I switched gears to using a Google Doc as my template and just try to replace elements in it instead. This went well until I got to the image.
Essentially no matter what I try to specify as the URI, it says the file in not in a supported format.
As far as I can tell, Google expects the URI to actually end in .png or be a real link versus a download URL you'd get from Google Drive.
Here is an example of the code I'm using to attempt to replace the image. The strImageObjectId is the objectId of the Embedded Object image in the template document copy that I want to replace. The Uri is what Google needs to pull the new image from. I'm happy to pull it from my local computer or Google Drive if only I could get it to accept it somehow.
BatchUpdateDocumentRequest batchUpdateRequest = new BatchUpdateDocumentRequest {
Requests = new List<Google.Apis.Docs.v1.Data.Request>()
};
request = new Google.Apis.Docs.v1.Data.Request {
ReplaceImage = new ReplaceImageRequest() {
ImageObjectId = strImageObjectId,
Uri = strChartWebContentLink
}
};
batchUpdateRequest.Requests.Add(request);
DocumentsResource.BatchUpdateRequest updateRequest =
sDocsService.Documents.BatchUpdate(batchUpdateRequest, strCopyFileId);
BatchUpdateDocumentResponse updateResponse = updateRequest.Execute();
I'm happy to use whatever method will get me to a point where I an end up with a Google Doc on Google Drive that was based on a template in which I can replace various text elements, but most importantly add/replace an image.
Thanks so much for the advice.
I got to the point were I believe I was specifying the URI correctly, but then I started getting an access forbidden error instead.
I didn't have time to hunt this one down, so I went back to creating an HTML template with my image, uploading as a Google Doc, exporting to PDF, and then uploading as a PDF. This ended up working because originally I was using a BMP as the file format and that is not supported by Google Docs, so I changed to a PNG instead and it worked just fine.
I think Google Docs needs to add the ability to add an image using a MemoryStream or some other programmatic base64 resource instead of purely being based on URIs and running into temporary upload or permission issues.
Hey I'm doing the same thing with you,
and I got this, by modify the download link format.
from this:
https://docs.google.com/uc?export=download&id={{YOUR GDRIVE IMAGE
ID}
to this
https://docs.google.com/uc?export=view&id={{YOUR GDRIVE IMAGE ID}
e.g :
uri: "https://docs.google.com/uc?export=view&id=1cjgyHqtYSgS0CBT4x-9eQIHRzOIfGgv-"
but the image should be set for public privilege

BitmapFrame - No imaging component suitable to complete this operation was found [duplicate]

I'm downloading in image from web to save it locally. It works great with any other image formats but it this method below fails with an argument exception when I try to read a WebP image.
private static Image GetImage(string url)
{
try
{
HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(url);
HttpWebResponse response = (HttpWebResponse)request.GetResponse();
return Image.FromStream(response.GetResponseStream());
}
catch
{
return null;
}
}
How do you read .webp images in C#?
I found this other question that allows for converting between types but I do not want to do that WebP library for C#
Reason I'm not wanting to do it is because I think it might lose some quality. Besides, I want to know why is this not working.
The base class libraries won't help you to deal with WebP images. However, if you only want to save the received file to the disk, you don't have to even know that you are dealing with a WebP images. You can simply treat the received data as a binary blob and dump it to a file, for example using Stream.CopyTo and a FileStream.
The Content-Type HTTP header will give you the mime type of the file you're downloading, and the Content-Disposition header can provide you with a filename and extension (though you might have to do some parsing). You can access those using HttpWebResponse.ContentType and HttpWebResponse.Headers["Content-Disposition"].
#Trillian nailed it. Here is a code snippet for what I did based on his suggestion. Wanted to add code so not posting this as a comment.
To get just the image file extension, you can do this
HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(url);
HttpWebResponse response = (HttpWebResponse)request.GetResponse();
string fileExt = response.ContentType.Replace("image/", string.Empty);
To get the file name with extension, you can do the following and the do parsing like I did above. It just has some more data in it.
response.Headers["Content-Disposition"];
Once you have you file name you want to save as, create a file stream and copy the response stream into it.
FileStream fs = new FileStream(targetPath + fileName, FileMode.Create);
response.GetResponseStream().CopyTo(fs);
Assuming you app has access to the destination, image should get saved. Make sure to add try catch and handle exceptions properly. Also note that FileMode.Create will overwrite if the file already exists!

Moving XML file to be hosted

Please be gentle. I am not a terribly proficient developer!
So this is the last thing I need to fix in my Windows Phone 7.5 app before I consider it done. In short, the data sources on the menus are driven by an xml file. That file is stored locally with the app. I would like to store that file somewhere on the Internet). Currently if I need to make a change to this xml file, I have to re-submit the app to the Marketplace taking about 5 days before the change goes live. How 2003 of me.
So I can't figure out what they are expecting returned in the code below. I've hacked away and it always give some error I don't understand.
I've set the filename variable to a URL of a file on the Internet but apparently that is not supported. So I either need a new way for that whole section to work or a way to convert the hosted filename converted into something that will work.
private static void FirstLaunch()
{
// On the first launch, just add everything from the OPML file
string filename;
//This file should really be hosted on the Internet somewhere.
filename = "/RSSReader;component/LyncNews-opml.xml";
StreamResourceInfo xml = App.GetResourceStream(new Uri(filename, UriKind.Relative));
List<RSSPage> rssPages = ParseOPML(xml.Stream);
}
You can set it to a URL, but you'll need to download the content, not through App.GetResourceStream. Try WebClient, it's easy and simple.
A simple usage:
WebClient client = new WebClient();
client.DownloadStringCompleted += new DownloadStringCompletedEventHandler(Client_DownloadStringCompleted);
Uri token = new Uri("your url");
client.DownloadStringAsync(token);
and handle xml parsing in the event.

Corrupted images after uploading

I am having a really weird issue with my image saving method. First, here is the method:
public static void uploadImageToServer(string savePath, HttpPostedFile imageToUpload, bool overwrite)
{
byte[] myData = new Byte[imageToUpload.ContentLength];
imageToUpload.InputStream.Read(myData, 0, imageToUpload.ContentLength);
FileStream newFile = new FileStream(savePath, FileMode.Create);
newFile.Write(myData, 0, myData.Length);
newFile.Close();
}
As you can see from the input parameters this method works in conjuction with the FileUpload control. Now I am using this method from two pages which both have a FileUpload control. On one page the image uploads file, on the other page it results in a corrupted file.
I am really at a loss as to why the image is being corrupted. I am using the same image, the same method, and the same input control.
Is there any way I can debug this?
Gonna steal alexn's answer <_<
You are over-complicating it. Just use the built-in FileUpload::SaveAs(save_path) that is provided for you.
You can use the Server.MapPath() method to help you get a dynamic path to your root directory, go from there and append the file name to it.
Not sure why you are getting that error. My best guess is either your savePath is broken (or the filename/extension appended to it), or the bytes are not being read/written to perfectly.. Anyway, you should not get that error by using the method I described (considering you don't mess up the file extension :).

WebClient.OpenReadAsync() corrupts JSON data. Why?

I have a class in my Silverlight app that (de-)serializes JSON strings to/from an object class.
I use WebClient.OpenReadAsync to get a file that contains this JSON string:
{"FirstName":"Bob","LastName":"Underwood"}
After calling OpenReadAsync however, the retrieved string has a lot of extra characters:
"PK\n\0\0\0\0\0�u�>h��5\0\0\05\0\0\0\t\0\0\0test.json\"{\\\"FirstName\\\":\\\"Gary\\\",\\\"LastName\\\":\\\"MacDonald\\\"}\"PK\0\n\0\0\0\0\0�u�>h��5\0\0\05\0\0\0\t\0\0\0\0\0\0\0\0\0 \0\0\0\0\0\0\0test.jsonPK\0\0\0\0\0\07\0\0\0\\\0\0\0\0\0"
This is the code I'm using to download the JSON:
WebClient client = new WebClient();
client.OpenReadCompleted += client_OpenReadCompleted;
client.OpenReadAsync(new Uri("/someJsonFile.zip", UriKind.Relative));
void client_OpenReadCompleted(object sender, OpenReadCompletedEventArgs e) {
if (e.Error == null) {
StreamReader reader = new StreamReader(e.Result);
string jsonString = reader.ReadToEnd().ToString();
}
else {
addMessage("Error " + e.Error.ToString());
}
}
jsonString ends up with all that extra data, so I can't deserialize it as is.
Another thing to note: the URI points to someJsonFile.zip, but it's really not zipped, when I give the file a extension like .json, or no extension, I get a error that it cannot find the file, but when I give it a extension like .zip, it finds it fine. Is there a way I can use a normal or no extension? I was wondering if this was a configuration issue.
Questions:
Am I doing something wrong in pulling this file and using StreamReader to get the string that's causing me to get all that trash data?
Do I need to do something specific to be able to use WebClient to grab a file with different extensions, like .json, or even no extension at all?
1 - That data stream certainly is a ZIP (PK is the old PKZip marker and the test.json filename is mentioned in its index as well).
Your server may be setup to serve all files compressed (or you may simply be accessing an actual zip file). Please check the server settings.
2 - As for the second question, the WebClient does not care about file types. It is just a stream of data that needs to be interpreted by something that knows what the data is (i.e. your code).
It is only the server that may be configured to serve up different files in different ways.
I was able to figure things out with my domain provider, appears to have been some configuration issues on their end.

Categories

Resources