export chinese, japanese character in .csv file + mvc3 - asp.net-mvc-3

I am using following code to export the content to .cvs file
which also support chinese and japanese characters.
public ActionResult Download(strng accnumber)
{
string csvContent = "东西,东西,东西, hi";
var data = Encoding.UTF32.GetBytes(csvContent );
string filename = "CSV_" + accnumber + ".csv";
return File(data, "text/csv", filename);
}
when i export my file i am not getting proper chinese or japanese characters. what is missing?
i have used UTF32 encoding to support it.
Edited:
i have noticed that opening my .csv file in notepad shows perfect characters but ms-excel doesn't.

I am also got same problem, solve it by using UTF-8-BOM.
Encoding.UTF8.GetPreamble().Concat(Encoding.UTF8.GetBytes(stringData)).ToArray()

As you are on asp.net serving that file you also have to deal with the encoding of the http pipleline. I din't spot that earlier, sorry.
Instead of having a plain ActionResult you should use one of the derived ActionResults, I've used FileContentResult. Please pay note to the special ContentType I'm constructing to tell the browsers an UTF-32 file is coming...
public ActionResult Download(string accnumber)
{
string csvContent = "东西,东西,东西, hi";
var data = Encoding.UTF8.GetBytes(csvContent);
// add byte order mark
var bom = new byte[] { 0xEF, 0xBB, 0xBF };
// hold it all
var all = new byte[bom.Length + data.Length];
// copy over BOM
Array.Copy(bom, all, bom.Length);
// copy over data
Array.Copy(data, 0, all, bom.Length, data.Length);
string filename = "CSV_" + accnumber + ".csv";
var file = new FileContentResult( all, "text/csv" )
{
FileDownloadName = filename
};
return file;
}

I encountered this problem too. I fix it by adding the following line just before "return file ;" and it works for me.
Response.Write("<meta http-equiv=Content-Type content=text/html;charset=utf-8>");
return file;

Related

How to create a string for #Html.ActionLink that concatenates an integer from the Model and a string

I'm using VS2015, MVC 5 design model. Creating a link that says "View" to open a PDF file in a new browser tab. It works fine, but the document sub-directory is hard-coded in the controller. I need to pass the document sub-directory + filename to the controller. The document sub-directory is the same as the Model.id . I'm having a difficult time converting the Model.id to a string and concatenating with the filename.
The following code in the view works fine with the hard-coded sub-directory in the controller
<td>#Html.ActionLink("View", "ViewAttachedDoc", "Documents", new { filename = item.filename}, new { target = "_blank" })</td>
But this code does not work
<td>#Html.ActionLink("View", "ViewAttachedDoc", "Documents", new { filename = Convert.ToString(Model.id) + "\" + item.filename }, new { target = "_blank" })</td>
The controller action is:
public FileResult ViewAttachedDoc(string filename)
{
string DocPath = ConfigurationManager.AppSettings["DocPath"];
string path = Path.Combine(DocPath, filename);
return File(path, "application/pdf");
}
TIA,
Tracy
The issue is likely from trying to pass a backslash through the URL. This link of a similar question has that same problem and their solution was to use HttpUtility.UrlEncode(value); and HttpUtility.UrlDecode(value);. Otherwise if that still doesn't work, what error are you getting?
P.S. C# automatically converts / -> \ for retrieving files.

File extension for tab-delimited values that can be opened by Excel?

I'm outputting a tab-delimited file from my webapp that should be opened in Excel. The problem is that .xls seems not good for opening and editing it, then Excel required some other format, and if I change the extension to .tsv then the file becomes unknown for Excel (on Windows 7) and .csv is for comma-separated. Can you advice me which the file extension should be?
This is the code that outputs the file and it works. It's just that I should choose the most suitable extension for tab-separated values.
#RequestMapping(value = "/export", method = RequestMethod.GET)
#ResponseBody
public ModelAndView export(HttpServletResponse response) {
try {
String str = "";
Iterator<Individual> iterator = customerAccountService.getAllIndividuals().iterator();
while(iterator.hasNext()){
Individual individual = iterator.next();
str = str + individual.getId() + "\t" +individual.getIndividualName().getName() + "\t" + individual.getAddress().getStreetName() + "\n";
}
InputStream is = new ByteArrayInputStream(str.getBytes());
IOUtils.copy(is, response.getOutputStream());
response.setContentType("application/xls");
response.setHeader("Content-Disposition","attachment; filename=export.tsv");
response.flushBuffer();
} catch (IOException ex) {
//logger.info("Error writing file to output stream. Filename was '" + fileName + "'");
throw new RuntimeException("IOError writing file to output stream");
}
ModelAndView modelAndView = new ModelAndView(ViewName.MENU);
modelAndView.addObject(ObjectName.ADD_FORM, new LoginForm());
return modelAndView;
}
Put
sep=\t
as the first line in your .csv-file (yes, you can name it .csv then). That tells excel what the delimiter character should be.
Note, that actually if you open the .csv with a text editor, it should read like
sep= (an actual tabulator character here, it's just not visible...)

Uploading images with redactor to MVC

This might be a bit too specific for here and I may need to contact redactor support but i've seen other questions about redactor here so i figured i'd give it a shot ...
Ok ...
So i'm trying to get get image uploading to work following the example here ...
http://imperavi.com/redactor/docs/images/
My client side code ...
$("textarea").redactor({
focus: true,
imageUpload: '/MyController/UploadImage'
});
My MVC controller action looks like this ...
public JsonResult UploadImage(object image)
{
// Do something with whatever that was i got from redactor
var result = new { filelink = "" };
return Json(result);
}
The problem is ... what did redactor actually give me?
Was it the whole file? a chunk? i can't seem to tell because the object has no type information at all and the raw post information seems way too little to actually be a whole image file.
Has anyone had any experience with this / actually done it before?
I don't really want to setup php on my server for this 1 function.
EDIT:
Ok a bit more digging reveals that if i pull the underlying Request object it has a files property which apparently contains my posted image file.
I think i might be able to figure it out from here.
Where I get a code block in place i'll post it as an answer.
You are receiving a HttpPostedFileBase object. Here is my implementation:
jQuery:
$('#blog-post').redactor(
{
imageUpload: '/blog/images/',
imageGetJson: '/images/locations/blogs/'
});
Then in the controller:
public ActionResult Images(HttpPostedFileBase file)
{
// Verify that the user selected a file
if( file != null && file.ContentLength > 0 )
{
// extract only the fielname
var fileName = Path.GetFileName( file.FileName );
// store the file
var path = Path.Combine( ImageLocation.BlogPicturePath, fileName );
file.SaveAs( path );
}
return Json( new { filelink = ImageLocation.BlogPictureUrl + "/" + file.FileName } );
}
ok um ... i think im there ...
This needs a bit of cleaning up and I don't expect you guys to understand what goes on under the bonnet of my custom DMS code but just assume it takes the stream and returns a FileInfo object and in theory this should work for you too ...
public ActionResult Upload()
{
// this object is specific to my system but all it does is
// stream the file to a path on the server (code not needed for this Q)
var dmsService = _kernel.Get<IDMSFileSystemService>();
List<FileInfo> savedFiles = new List<FileInfo>();
for (int i = 0; i < Request.Files.Count; i++)
{
var file = Request.Files[i];
using (file.InputStream)
{
savedFiles.Add(dmsService.AddFromStream(file.InputStream, file.FileName);
}
}
var result = savedFiles.Select(f => new { filelink = f.Path}).ToArray();
return Json(result);
}
Suprisingly simple right ... :)

How to get more information from a InputStremed file?

If I'm using the InputStream to receive a file, like
HttpContext.Current.Request.InputStream
How can get more information about the file?
I can easily convert a Stream into a phisical File, but for example, how would I know the file extension in use?
string fileIn = #"C:\Temp\inputStreamedFile.xxx"; // What extension?
using (FileStream fs = System.IO.File.Create(fileIn))
{
Stream f = HttpContext.Current.Request.InputStream;
byte[] bytes = new byte[f.Length];
f.Read(bytes, 0, (int)f.Length);
fs.Write(bytes, 0, bytes.Length);
}
The idea behind this is because using HttpPostedFileBase I always get null:
public ContentResult Send(HttpPostedFileBase fileToUpload, string email)
{
// Get file stream and save it
// Get File in stream
string fileIn = Path.Combine(uploadsPath, uniqueIdentifier),
fileOut = Path.Combine(convertedPath, uniqueIdentifier + ".pdf");
// Verify that the user selected a file
if (fileToUpload != null && fileToUpload.ContentLength > 0)
{
// extract only the fielname
string fileExtension = Path.GetExtension(fileToUpload.FileName);
fileIn = String.Concat(fileIn, fileExtension);
fileToUpload.SaveAs(fileIn);
}
// TODO: Add Convert File to Batch
return Content("File queued for process with id: " + uniqueIdentifier);
}
and this is what I'm sending from the command line:
$ curl --form email='mail#domain.com' --form fileToUpload='C:\temp\MyWord.docx' http://localhost:64705/send/
File queued for process with id: 1d777cc7-7c08-460c-8412-ddab72408123
the variable email is filled up correctly, but fileToUpload is always null.
P.S. This does not happen if I use a form to upload the same data.
I'm sorry if this doesn't help, but why use InputStream to get uploaded file(s) ?
This is what I usually do:
[HttpPost]
public ActionResult Upload(HttpPostedFileBase[] files) {
String physicalPath = "c:\\whatever";
foreach (var file in files) {
String extension = Path.GetExtension(file.FileName);
file.SaveAs(physicalPath + "\\" + file.FileName);
}
return View();
}
The only problem I found was using curl... I was forgetting the # sign that mention that the uploaded form would be encoded as multipart/form-data.
The correct curl command to use HttpPostedFileBase would be:
$ curl --form email='mail#domain.com'
--form fileToUpload=#'C:\temp\MyWord.docx'
http://localhost:64705/send/
You can get the info about posted file from <input type="file" />. But actually it's used a bit different way to upload files in asp.net mvc check out here

How do I read the Received Date from Outlook MSG files -without- the Outlook API?

I need to read stuff from an Outlook msg file. Currently I'm using a class from CodeProject.com project to accomplish this, since deploying VSTO and Outlook on a server is not an option.
This class gets To, From, CC, Subject, Body, and everything else I need from the msg file, except Date information (such as Received Date and Sent Date).
There is some (really, really low-level) documentation on how to get stuff out of msg files on MSDN, but it's a little beyond the scope of this project and doesn't mention dates at all.
Ideally I'd be able to have a drop-in replacement for the class I am using now (OutlookStorage.cs in the previously mentioned CodeProject) or be able to modify the existing class a bit. To modify, I would need the correct 4 character hexidecimal prop identifier for received date. For instance, Subject is listed as PR_SUBJECT = "0037" and Body is listed as PR_BOY = "1000".
If you're using OutlookStorage.cs from CodeProject, then add the following:
private const string PR_RECEIVED_DATE="007D";
private const string PR_RECEIVED_DATE_2 = "0047";
...
/// <summary>
/// Gets the date the message was received.
/// </summary>
public DateTime ReceivedDate
{
get
{
if (_dateRevieved == DateTime.MinValue)
{
string dateMess = this.GetMapiPropertyString(OutlookStorage.PR_RECEIVED_DATE);
if (String.IsNullOrEmpty(dateMess))
{
dateMess = this.GetMapiPropertyString(OutlookStorage.PR_RECEIVED_DATE_2);
}
_dateRevieved = ExtractDate(dateMess);
}
return _dateRevieved;
//return ExtractDate(dateMess);
}
}
private DateTime _dateRevieved = DateTime.MinValue;
private DateTime ExtractDate(string dateMess)
{
string matchStr = "Date:";
string[] lines = dateMess.Split(new String[] { "\r\n" }, StringSplitOptions.RemoveEmptyEntries);
foreach (string line in lines)
{
if (line.StartsWith(matchStr))
{
string dateStr = line.Substring(matchStr.Length);
DateTime response;
if (DateTime.TryParse(dateStr, out response))
{
return response;
}
}
}
return DateTime.MinValue;
}
I think the Aspose library will do what you want, ok it a 3rd party lib so may not be what you want. There are a few vbs scripts around that get basic infomation out of msg files that could be translated.
Got a hint from this:
string fullFileName = "c:\message.msg";
DateTime dateRevieved = new DateTime();
StreamReader sr = new StreamReader(fullFileName, Encoding.Default);
string full = sr.ReadToEnd();
string date;
int iStart;
int iLast;
string caption;
//This -should- handle all manner of screwage
//The ONLY way it would not is if someone guessed the -exact- to-the-second
//time that they send the message, put it in their subject in the right format
while (true) { //not an infinite loop, I swear!
caption = "Date:";
if (full.IndexOf("Date:") > -1) { //full shortens with each date is removed
string temp = "";
iStart = full.LastIndexOf(caption);
temp = full.Remove(0, iStart + caption.Length);
full = full.Substring(0, iStart);
iLast = temp.IndexOf("\r\n");
if (iLast < 0) {
date = temp;
} else {
date = temp.Substring(0, iLast);
}
date = date.Trim();
if (date.Contains(subject) || subject.Contains(date)) {
continue; //would only happen if someone is trying to screw me
}
try {
dateRevieved = DateTime.Parse(date); //will fail if not a date
break; //if not a date breaks out of while loop
} catch {
continue; //try with a smaller subset of the msg
}
} else {
break;
}
}
This is kind of a hack compared to the ways you can get other things from msg files using something this lovely project. Still, it's stood up to everything I have thrown against it, and as noted the -only- way to fool it is to put the exact to-the-second date in the subject line in the proper format.
to combine your two posts I would suggest the following solution:
To modify, I would need the correct 4 character hexidecimal prop identifier for recieved date. For instance, Subject is listed as PR_SUBJECT = "0037" and Body is listed as PR_BOY = "1000".
Look for "007D".
Use the method you posted in your second post on the received data to eliminate the problem when the same (date) string is inside the subject.
I have to mention that this method doesn't seem to work on internal eMails: In mails I receive from colleagues, there is no substg1.0_007Dxxxx-Property.
Here, the date seems to be hidden in substg1.0_0047xxxx.
All the best!
inno

Resources