Accented characters of a vCard not displaying in Windows Contacts - asp.net

I am writing a method that allows a user to generate a vCard file based on some information. It works quite well and the user can open the generated file with Microsoft Outlook without any problem (tested on versions 2010 and 2013). But when he wants to open it with Windows Contacts, the accented characters are not well displayed whereas I have set the charset to the different fields to UTF-8.
Here is an example of a generated vCard:
BEGIN:VCARD
VERSION:4.0
FN;CHARSET=utf-8:Vandenbergh Cédric
N;CHARSET=utf-8:Vandenbergh;Cédric;;;
TITLE;CHARSET=utf-8:Manager d'entité
END:VCARD
And here is what I get when opening it with Windows Contacts:
Could it be a bug in Windows Contacts (tested under Windows 8.1)? Or am I missing something?
Edit
Here is the code I use for a user to download a vCard:
Context.Response.Clear();
Context.Response.Buffer = true;
Context.Response.ContentType = "text/x-vCard; charset=utf-8";
Context.Response.AddHeader("Content-Disposition", "attachment;filename=file.vcf");
Context.Response.Write(user.GetVCard()); // Get vCard content
Context.Response.Flush();
Context.Response.End();
Edit 2/10/15
I still have no idea on how to solve this problem. In my opinion, it could really be a Windows Contacts bug but I cannot find anything on the web to confirm my impression.

Just because you add a "CHARSET=utf-8" parameter doesn't mean the value will be written in UTF-8. You are probably not setting the character encoding to "UTF-8" when you write the vCard.
Also, note that vCard version 4.0 does not support the "CHARSET" parameter. The specification states that all vCards MUST be written in UTF-8.

Related

Prompting user for download, IE sets the filename as the .aspx name ("Would you like to download SomePage.aspx?fileID=12345")

I am at a loss here. I am trying to transmit a file on the local intranet site. When I get a download prompt in IE11, it says:
Do you want to open or save "SomePage.aspx?fileID=12345"? [open] [save] [cancel]
Instead of..
Do you want to open or save "Document.pdf"? [open] [save] [cancel]
It works perfectly fine on Chrome. The file gets downloaded with the correct filename. But for some reason, IE isn't setting the name and instead uses the ASPX name.
The code is rather straightforward:
testFile = New System.IO.FileInfo("\\someshare\somefolder$\Document.pdf")
Response.Clear()
Response.AddHeader("Content-Disposition", "attachment; filename=" & testFile.Name)
Response.AddHeader("Content-Length", testFile.Length.ToString())
Response.ContentType = "application/octet-stream"
Response.TransmitFile(testFile.FullName)
I've tried a number of different header options and the MIME type makes no difference.
Does anyone have a clue why this would be happening?
Notes: Not HTTPS. It is not limited to PDF, same happens with .TIF, .DOC, and every other format I've tested.
EDIT: Have also tried Response.WriteFile as well as Response.BinaryWrite .. same thing each time.
EDIT2: Simplified everything down to a single button on a completely blank page.
You should have quote marks around the file name. See 19.5.1 on http://www.w3.org/Protocols/rfc2616/rfc2616-sec19.html
i.e.
Content-Disposition: attachment; filename="fname.ext"
so...
Response.AddHeader("Content-Disposition", String.Format("attachment; filename=""{0}""", testFile.Name))
Unfortunately I have not been able to test if this solves your issue as I don't have access to IE11 at the moment.
So I know this question is older, but the solution I finally came up with to this problem is to add the following two lines to my code.
Response.SuppressContent = True
and
HttpContext.Current.ApplicationInstance.CompleteRequest()
You have said in previous comments that you have tried the CompleteRequest command to no avail.
As a note, I am not 100% certain to the logistics of the Response.SuppressContent() command.
The documentation says that it indicates "whether to send HTTP content to the client". This seems counter intuitive to the process of sending the request body back to the client, however, it appears to only suppress the parts of the response that include any HTML.
It seems that the partial or incomplete HTML is what causes the filename to appear as the page name regardless of the headers set and sent. Stripping this out should cause the file to download properly.
Interestingly, this solution is actually born out of a secondary issue where once I was able to export the file using ClosedXML, i was receiving messages when opening the document that there were errors than excel would try to fix.
Response.SuppressContent actually fixed that as well. Hope this helps or at least points you in the right direction.

Writing file to users giving sporadic error in IE

I have a very interesting issue with only specific IE implementations. I have an ASPX page that is used to write files down to the user, as part of the process the page uses the following code to write the file to the user.
Response.Clear();
Response.AddHeader("content-disposition", "attachment;filename=download" + System.IO.Path.GetExtension(oInfo.SupportingFilePath));
Response.ContentType = "application/octet-stream";
Response.WriteFile(Server.MapPath(oInfo.SupportingFilePath));
Response.End();
In 99.5% of the cases this works just fine, however, in certain rare circumstances within IE only on specific machines, the user is prompted to download the .aspx page, and/or is given an error message.
Anyone have an idea of what is going on here?
Per RFC2231, MIME headers' parameter values have to be included in double quotes: http://www.ietf.org/rfc/rfc2231.txt (page 3, if you are interested).
It should be something like "attachment;filename=""download" + System.IO.Path.GetExtension(oInfo.SupportingFilePath) + """");
Although this should not be happening because you've set the ContentType and content-disposition, I believe that IE's built-in MIME sniffing/handling is what is causing the problem here. Here are a couple of work-around/hacks you can try:
Add the file extension to the query string on the .aspx page that is transferring the file, i.e., http://blahblahblah/page.aspx?.ext
If you are using IE 8, you can specify another response header for "nosniff," as specified here.
I'm still having issues with this, as documented here, but I hope one of these helps.

Downloaded word file displaying incorrectly

I am working on a website at the moment which is displaying a strange bug with generated word documents. The site has a feature on it which allows the user to download a word document containing information related to their visit. This file is generated via some vb.net code and takes an xml template of the final document and inserts the relevant content required.
The strange behaviour is that on some machines the .doc file generated displays fine and on others it displays as XML when opened in Word. Both behaviours have been seen in the same version of Office (2003) but on seperate machines. My question is really whether the error lies with the set up of word on the individual machines, or whether there is an error in the code.
The code to create the file and download it is as follows:
Response.Clear()
Response.ClearHeaders()
Response.AddHeader("content-disposition", "inline; filename=MyNewFile")
Response.ContentType = "application/msword"
'Create the word file as a byte array based off an xml template document'
Dim objWordGenerator As New WordFileGenerator
Response.BinaryWrite(objWordGenerator.GetWordBytes)
Response.Flush()
Response.Clear()
Response.End()
The actual xml template is quite large so probably not suitable to post here but I can provide any more information if necessary.
Update:
Having managed to fix the original bug (it turns out that the original filename being used didn't have the .doc extension) I have found another bit of strange behaviour.
When the file is opened it opens in Word correctly, however when you go to save it the default file type is XML. When saved as an XML file it will open in Word correctly, but I feel this is slightly confusing behaviour for the end user. I would like the file to default to saving as a DOC file instead. Is there a way to force this to happen?
Update 2:
Below is a section of the XML that relates to the Document properties. The rest of the document deals with content and styles etc, so my assumption is that this is the most relevant section. To reiterate, my problem is that when the downloaded .doc file is opened in word, the default "save as" option is as an XML file.
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<?mso-application progid="Word.Document"?>
<w:wordDocument xmlns:w="http://schemas.microsoft.com/office/word/2003/wordml" xmlns:v="urn:schemas-microsoft-com:vml" xmlns:w10="urn:schemas-microsoft-com:office:word" xmlns:sl="http://schemas.microsoft.com/schemaLibrary/2003/core" xmlns:aml="http://schemas.microsoft.com/aml/2001/core" xmlns:wx="http://schemas.microsoft.com/office/word/2003/auxHint" xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:dt="uuid:C2F41010-65B3-11d1-A29F-00AA00C14882" w:macrosPresent="no" w:embeddedObjPresent="no" w:ocxPresent="no" xml:space="preserve">
<o:DocumentProperties>
<o:Title>Fancy Word Doc</o:Title>
<o:Author>Bob Bobertson</o:Author>
<o:Characters>999</o:Characters>
<o:Company>A Fancy Company</o:Company>
<o:Version>1.1.1</o:Version>
</o:DocumentProperties>
Cheers
The File -> SaveAs filetype is XML because that is what the file open in Word is. If you want it to say 'Word Document (*.doc) then you will need to create a real Word document on the server and not an XML. Just by putting a .doc extension on the filename doesn't change it's real contents. Word knows the file type that is loaded into it and suggests that as the file type when saving. I don't know of any way to override this behavior.
I've been using Office XML with Excel for awhile now and this is very similar to the code that I'm using to send it down to the client. You might want to try and see if it works for you.
Dim xml As XmlDocument = New XmlDocument()
xml.Load("report.doc")
Response.ContentType = "application/vnd.ms-word"
Response.AppendHeader("CONTENT-DISPOSITION", "attachment; filename=report.doc")
Response.Write(xml.OuterXml)
Try it with firefox and you will probably find that it will be saved with the correct extension.
IIRC, since version 3 IE prefers to ignore the mime type and sniff the file content to see what the "correct" file format is. Maybe is uses the magic cookie?
Is this Word 2007 or later? Try
Response.AddHeader("content-disposition", "attachment; filename='MyNewFile.doc'")
attachment encourages the browser to save the file instead of displaying it.
I ran some tests and could not reproduce your problem on my system in Word 2003. Without a specific example (and actual file that is misbehaving), it would be pure speculation to make any suggestions.

How do I send a binary blob to a client browser?

Pardon the dumb newbie question here; web programming isn't my forte... (blush)
I have an aspx page running on a web server. I have a blob (byte array) containing any kind of binary file, plus a file name.
I would like to push this file to be downloaded through the browser onto the client, and opened using whatever application is default for this file type. I really don't want to save the blob as a file on the server; that will leave a terrible housekeeping mess that I just don't want to think about.
I did try googling this question, but I guess I'm using the wrong keywords.
This really should be obvious how to do it, but I'm having no joy.
What is the trick?
Thanks!
Response.BinaryWrite(byteArray);
You should also set the content type
Response.ContentType = "application/pdf";
But that will be based on your file type.
And the file name (and everything together) is done like this
Response.AddHeader("content-disposition",
String.Format("attachment;filename={0}", fileName));
Response.ContentType = "application/pdf";
Response.BinaryWrite(byteArray);
First, you have to know the mime type. Once you know that, you can set the Response.ContentType property. After that, just use Response.BinaryWrite(). If you don't first set the ContentType property, the client will have almost no chance of opening the file correctly.

"name" web pdf for better default save filename in Acrobat?

My app generates PDFs for user consumption. The "Content-Disposition" http header is set as mentioned here. This is set to "inline; filename=foo.pdf", which should be enough for Acrobat to give "foo.pdf" as the filename when saving the pdf.
However, upon clicking the "Save" button in the browser-embedded Acrobat, the default name to save is not that filename but instead the URL with slashes changed to underscores. Huge and ugly. Is there a way to affect this default filename in Adobe?
There IS a query string in the URLs, and this is non-negotiable. This may be significant, but adding a "&foo=/title.pdf" to the end of the URL doesn't affect the default filename.
Update 2: I've tried both
content-disposition inline; filename=foo.pdf
Content-Type application/pdf; filename=foo.pdf
and
content-disposition inline; filename=foo.pdf
Content-Type application/pdf; name=foo.pdf
(as verified through Firebug) Sadly, neither worked.
A sample url is
/bar/sessions/958d8a22-0/views/1493881172/export?format=application/pdf&no-attachment=true
which translates to a default Acrobat save as filename of
http___localhost_bar_sessions_958d8a22-0_views_1493881172_export_format=application_pdf&no-attachment=true.pdf
Update 3: Julian Reschke brings actual insight and rigor to this case. Please upvote his answer.
This seems to be broken in FF (https://bugzilla.mozilla.org/show_bug.cgi?id=433613) and IE but work in Opera, Safari, and Chrome. http://greenbytes.de/tech/tc2231/#inlwithasciifilenamepdf
Part of the problem is that the relevant RFC 2183 doesn't really state what to do with a disposition type of "inline" and a filename.
Also, as far as I can tell, the only UA that actually uses the filename for type=inline is Firefox (see test case).
Finally, it's not obvious that the plugin API actually makes that information available (maybe someboy familiar with the API can elaborate).
That being said, I have sent a pointer to this question to an Adobe person; maybe the right people will have a look.
Related: see attempt to clarify Content-Disposition in HTTP in draft-reschke-rfc2183-in-http -- this is early work in progress, feedback appreciated.
Update: I have added a test case, which seems to indicate that the Acrobat reader plugin doesn't use the response headers (in Firefox), although the plugin API provides access to them.
Set the file name in ContentType as well. This should solve the problem.
context.Response.ContentType = "application/pdf; name=" + fileName;
// the usual stuff
context.Response.AddHeader("content-disposition", "inline; filename=" + fileName);
After you set content-disposition header, also add content-length header, then use binarywrite to stream the PDF.
context.Response.AddHeader("Content-Length", fileBytes.Length.ToString());
context.Response.BinaryWrite(fileBytes);
Like you, I tried and tried to get this to work. Finally I gave up on this idea, and just opted for a workaround.
I'm using ASP.NET MVC Framework, so I modified my routes for that controller/action to make sure that the served up PDF file is the last part of the location portion of the URI (before the query string), and pass everything else in the query string.
Eg:
Old URI:
http://server/app/report/showpdf?param1=foo&param2=bar&filename=myreport.pdf
New URI:
http://server/app/report/showpdf/myreport.pdf?param1=foo&param2=bar
The resulting header looks exactly like what you've described (content-type is application/pdf, disposition is inline, filename is uselessly part of the header). Acrobat shows it in the browser window (no save as dialog) and the filename that is auto-populated if a user clicks the Acrobat Save button is the report filename.
A few considerations:
In order for the filenames to look decent, they shouldn't have any escaped characters (ie, no spaces, etc)... which is a bit limiting. My filenames are auto-generated in this case, and before had spaces in them, which were showing up as '%20's in the resulting save dialog filename. I just replaced the spaces with underscores, and that worked out.
This is by no names the best solution, but it does work. It also means that you have to have the filename available to make it part of the original URI, which might mess with your program's workflow. If it's currently being generated or retrieved from a database during the server-side call that generates the PDF, you might need to move the code that generates the filename to javascript as part of a form submission or if it comes from a database make it a quick ajax call to get the filename when building the URL that results in the inlined PDF.
If you're taking the filename from a user input on a form, then that should be validated not to contain escaped characters, which will annoy users.
Hope that helps.
Try placing the file name at the end of the URL, before any other parameters. This worked for me.
http://www.setasign.de/support/tips-and-tricks/filename-in-browser-plugin/
In ASP.NET 2.0 change the URL from
http://www. server.com/DocServe.aspx?DocId=XXXXXXX
to
http://www. server.com/DocServe.aspx/MySaveAsFileName?DocId=XXXXXXX
This works for Acrobat 8 and the default SaveAs filename is now MySaveAsFileName.pdf.
However, you have to restrict the allowed characters in MySaveAsFileName (no periods, etc.).
Apache's mod_rewrite can solve this.
I have a web service with an endpoint at /foo/getDoc.service. Of course Acrobat will save files as getDoc.pdf. I added the following lines in apache.conf:
LoadModule RewriteModule modules/mod_rewrite.so
RewriteEngine on
RewriteRule ^/foo/getDoc/(.*)$ /foo/getDoc.service [P,NE]
Now when I request /foo/getDoc/filename.pdf?bar&qux, it gets internally rewritten to /foo/getDoc.service?bar&qux, so I'm hitting the correct endpoint of the web service, but Acrobat thinks it will save my file as filename.pdf.
If you use asp.net, you can control pdf filename through page (url) file name.
As other users wrote, Acrobat is a bit s... when it choose the pdf file name when you press "save" button: it takes the page name, removes the extension and add ".pdf".
So /foo/bar/GetMyPdf.aspx gives GetMyPdf.pdf.
The only solution I found is to manage "dynamic" page names through an asp.net handler:
create a class that implements IHttpHandler
map an handler in web.config bounded to the class
Mapping1: all pages have a common radix (MyDocument_):
<httpHandlers>
<add verb="*" path="MyDocument_*.ashx" type="ITextMiscWeb.MyDocumentHandler"/>
Mapping2: completely free file name (need a folder in path):
<add verb="*" path="/CustomName/*.ashx" type="ITextMiscWeb.MyDocumentHandler"/>
Some tips here (the pdf is dynamically created using iTextSharp):
http://fhtino.blogspot.com/2006/11/how-to-show-or-download-pdf-file-from.html
Instead of attachment you can try inline:
Response.AddHeader("content-disposition", "inline;filename=MyFile.pdf");
I used inline in a previous web application that generated Crystal Reports output into PDF and sent that in browser to the user.
File download dialog (PDF) with save and open option
Points To Remember:
Return Stream with correct array size from service
Read the byte arrary from stream with correct byte length on the basis of stream length.
set correct contenttype
Here is the code for read stream and open the File download dialog for PDF file
private void DownloadSharePointDocument()
{
Uri uriAddress = new Uri("http://hyddlf5187:900/SharePointDownloadService/FulfillmentDownload.svc/GetDocumentByID/1/drmfree/");
HttpWebRequest req = WebRequest.Create(uriAddress) as HttpWebRequest;
// Get response
using (HttpWebResponse httpWebResponse = req.GetResponse() as HttpWebResponse)
{
Stream stream = httpWebResponse.GetResponseStream();
int byteCount = Convert.ToInt32(httpWebResponse.ContentLength);
byte[] Buffer1 = new byte[byteCount];
using (BinaryReader reader = new BinaryReader(stream))
{
Buffer1 = reader.ReadBytes(byteCount);
}
Response.Clear();
Response.ClearHeaders();
// set the content type to PDF
Response.ContentType = "application/pdf";
Response.AddHeader("Content-Disposition", "attachment;filename=Filename.pdf");
Response.Buffer = true;
Response.BinaryWrite(Buffer1);
Response.Flush();
// Response.End();
}
}
I believe this has already been mentioned in one flavor or another but I'll try and state it in my own words.
Rather than this:
/bar/sessions/958d8a22-0/views/1493881172/export?format=application/pdf&no-attachment=true
I use this:
/bar/sessions/958d8a22-0/views/1493881172/NameThatIWantPDFToBe.pdf?GeneratePDF=1
Rather than having "export" process the request, when a request comes in, I look in the URL for GeneratePDF=1. If found, I run whatever code was running in "export" rather than allowing my system to attempt to search and serve a PDF in the location /bar/sessions/958d8a22-0/views/1493881172/NameThatIWantPDFToBe.pdf. If GeneratePDF is not found in the URL, I simply transmit the file requested. (note that I can't simply redirect to the file requested - or else I'd end up in an endless loop)
You could always have two links. One that opens the document inside the browser, and another to download it (using an incorrect content type). This is what Gmail does.
For anyone still looking at this, I used the solution found here and it worked wonderfully. Thanks Fabrizio!
The way I solved this (with PHP) is as follows:
Suppose your URL is SomeScript.php?id=ID&data=DATA and the file you want to use is TEST.pdf.
Change the URL to SomeScript.php/id/ID/data/DATA/EXT/TEST.pdf.
It's important that the last parameter is the file name you want Adobe to use (the 'EXT' can be about anything). Make sure there are no special chars in the above string, BTW.
Now, at the top of SomeScript.php, add:
$_REQUEST = MakeFriendlyURI( $_SERVER['PHP\_SELF'], $_SERVER['SCRIPT_FILENAME']);
Then add this function to SomeScript.php (or your function library):
function MakeFriendlyURI($URI, $ScriptName) {
/* Need to remove everything up to the script name */
$MyName = '/^.*'.preg_quote(basename($ScriptName)."/", '/').'/';
$Str = preg_replace($MyName,'',$URI);
$RequestArray = array();
/* Breaks down like this
0 1 2 3 4 5
PARAM1/VAL1/PARAM2/VAL2/PARAM3/VAL3
*/
$tmp = explode('/',$Str);
/* Ok so build an associative array with Key->value
This way it can be returned back to $_REQUEST or $_GET
*/
for ($i=0;$i < count($tmp); $i = $i+2){
$RequestArray[$tmp[$i]] = $tmp[$i+1];
}
return $RequestArray;
}//EO MakeFriendlyURI
Now $_REQUEST (or $_GET if you prefer) is accessed like normal $_REQUEST['id'], $_REQUEST['data'], etc.
And Adobe will use your desired file name as the default save as or email info when you send it inline.
I was redirected here because i have the same problem. I also tried Troy Howard's workaround but it is doesn't seem to work.
The approach I did on this one is to NO LONGER use response object to write the file on the fly. Since the PDF is already existing on the server, what i did was to redirect my page pointing to that PDF file. Works great.
http://forums.asp.net/t/143631.aspx
I hope my vague explanation gave you an idea.
Credits to Vivek.
Nginx
location /file.pdf
{
# more_set_headers "Content-Type: application/pdf; name=save_as_file.pdf";
add_header Content-Disposition "inline; filename=save_as_file.pdf";
alias /var/www/file.pdf;
}
Check with
curl -I https://example.com/file.pdf
Firefox 62.0b5 (64-bit): OK.
Chrome 67.0.3396.99 (64-Bit): OK.
IE 11: No comment.
Try this, if your executable is "get.cgi"
http://server,org/get.cgi/filename.pdf?file=filename.pdf
Yes, it's completely insane. There is no file called "filename.pdf" on the server, there is directory at all under the executable get.cgi.
But it seems to work. The server ignores the filename.pdf and the pdf reader ignores the "get.cgi"
Dan

Resources