I'm trying to copy an sqlite database from the root bundle onto the file system in order to use it.
I've tried many different ways but it always ended up writing incorrect amounts of data to disk. The code I'm using looks like this:
Directory appDocDir = await getExternalStorageDirectory();
String path = join(appDocDir.path, "data.db");
bool exists = await new File(path).exists();
if (!exists) {
var out = new File(path).openWrite();
var data = await rootBundle.load("assets/data.sqlite");
var list = data.buffer.asUint8List();
out.write(list);
out.close();
}
I was able to do that by the followings.
ByteData data = await rootBundle.load("data.sqlite");
List<int> bytes = data.buffer.asUint8List(data.offsetInBytes, data.lengthInBytes);
Directory appDocDir = await getApplicationDocumentsDirectory()
String path = join(appDocDir.path, "data.db");
await File(path).writeAsBytes(bytes);
You can't write the contents of a Uint8List to a File using IOSink.write (which is designed to operate on String arguments). You'll end up writing the UTF-8 encoded representation of the String obtained by calling toString() on your Uint8List, which is probably much larger than the actual contents of the list.
Instead, you can write a Uint8List to the file using IOSink.add.
In the example you've provided, you could also write the entire file at once using new File(path).writeAsBytes(list).
Related
I am trying to get base64 string from image file. When I am using following method
Future convertBase64(file) async{
List<int> imageBytes = fileImage.readAsBytesSync();
String base64Image = await 'data:image/png;base64,' + base64Encode(imageBytes);
// print('length of image bytes ${base64Image.length}');
return base64Image;
}
It shows me an error :
exception---- Converting object to an encodable object failed: Instance of 'Future<dynamic>'
If I use without future it directly pass to next step without converting to base64 String. It usually takes time to convert.
The variable fileImage doesn't seem to match the variable file passed to the function. Might this be the one causing the issue?
I'm curious on why the need to call await on a String - this seems to be unnecessary. The error might be caused on how convertBase64() was called. For async methods like Future<T>, I suggest calling it like:
convertBase64(imageFile).then((String base64Image) {
// Handle base64Image
});
Also, as previously recommended in the comments, it's better to use Uri.dataFromBytes() instead of parsing the encoded String on your own.
Future<String> convertBase64(File file) async{
List<int> imageBytes = file.readAsBytesSync();
return Uri.dataFromBytes(imageBytes, mimeType: "image/png").toString();
}
I am trying to use the Rotativa component to store (not to show) a copy of the invoice permanently on web server disk. Two questions:
Why I need to specify a controller action? ("Index", in this
case)
How do I write the FileContentResult on local disk without
displaying it?
Thanks.
Here is my code:
[HttpPost]
public ActionResult ValidationDone(FormCollection formCollection, int orderId, bool fromOrderDetails)
{
Order orderValidated = context.Orders.Single(no => no.orderID == orderId);
CommonUtils.SendInvoiceMail(orderValidated.customerID , orderValidated.orderID);
var filePath = Path.Combine(Server.MapPath("/Temp"), orderValidated.invoiceID + ".pdf");
var pdfResult = new ActionAsPdf("Index", new { name = orderValidated.invoiceID }) { FileName = filePath };
var binary = pdfResult.BuildPdf(ControllerContext);
FileContentResult fcr = File(binary, "application/pdf");
// how do I save 'fcr' on disk?
}
You do not need the FileContentResult to create a file. You've got the byte array which can be saved directly to the disk:
var binary = pdfResult.BuildPdf(ControllerContext);
System.IO.File.WriteAllBytes(#"c:\foobar.pdf", binary);
string FileName="YOUR FILE NAME";
//first give a name to file
string Path=Server.MapPath("YourPath in solution"+Filename+".Pdf")
//Give your path and file extention. both are required.
binary[]= YOUR DATA
//Describe your data to be save as file.
System.IO.File.WriteAllBytes(Path, binary);
Thats simple...
I am using EPPlus to create an Excel file from a CSV which works without issue. Unfortunately, the below code causes Internet Explorer 9, 10, and 11 to drop the .xlsx file extension, while Chrome and Firefox do not. If I remove the spaces from the file name the file extension works as expected in IE.
public FileStreamResult DetailsExcel(string id)
{
string custName;
var csv = this.GetCsvForCustomer(id, out custName);
var fileName = String.Format("Report for {0} ({1:d-M-yyyy HH mm})",
custName, DateTime.Now);
MemoryStream stream;
using (var excelPackage = new ExcelPackage())
{
var ws = excelPackage.Workbook.Worksheets.Add(fileName);
ws.Cells["A1"].LoadFromText(csv, this._excelTextFormat);
stream = new MemoryStream(excelPackage.GetAsByteArray());
}
return File(stream,
"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
fileName + ".xlsx");
}
The two programmatic mechanisms that I have found that somewhat work are to wrap the file name in quotes or to UrlEncode the string. Each have issues:
String.Format("\"{0}\".xlsx", fileName)
// above renders: __Report for Customer (20-2-2014 11 04)__.xlsx
HttpUtility.UrlEncode(fileName + ".xlsx")
// above renders: Report+for+Customer+(20-2-2014+11+04).xlsx
Neither of the above are optimal. How do I include spaces in a file name without losing the file extension when a user is browsing with IE?
I haven't been able to reproduce the behavior you describe in a similar application that I have. The only difference is that I'm not loading the byte array into a MemoryStream first, but just passing the byte array to File.
So try removing the MemoryStream from the equation. So the code would end up something like:
public ActionResult DetailsExcel(string id)
{
byte[] stream; // changed to byte array
using (var excelPackage = new ExcelPackage())
{
var ws = excelPackage.Workbook.Worksheets.Add(fileName);
ws.Cells["A1"].LoadFromText(csv, this._excelTextFormat);
stream = excelPackage.GetAsByteArray(); // removed MemoryStream
}
return File(stream,
"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
fileName + ".xlsx");
}
In the image folder, the filename is arranged by Country_State_Date.jpg. Example : Usa_LA_4_jul.jpg. I need to get all the image filename which contain Usa. How should I go about it? Thanks
If your files are in isolated storage, you could get them with GetFileName() e.g.
using (IsolatedStorageFile f = IsolatedStorageFile.GetUserStoreForApplication())
{
f.GetFileNames("Images/USA*");
}
If they are in your project directory, then I would recommend setting the build action to 'Embedded Resource' and then you can get them by doing something along the lines of
Assembly currentAssembly = Assembly.GetExecutingAssembly();
string[] allResources = currentAssembly.GetManifestResourceNames();
string[] usaResources = allResources.Where(a => a.Contains("USA")).ToArray();
// get which ever stream you want from this collection
Stream imageStream = currentAssembly.GetManifestResourceStream(usaResources.First());
Then when you wanted to read the data from the file you just need to create a bitmap image with that stream as the image source.
var bitmapImage = new BitmapImage();
bitmapImage .SetSource(imageStream);
img.Source = bitmapImage ;
I have an word file that contain my specified pattern text {pattern} and I want to replace those pattern with new my string which was read from database. So I used open xml read stream from my docx template file the replace my pattern string then returned to stream which support to download file without create a temporary file. But when I opened it generated me error on docx file. Below is my example code
public ActionResult SearchAndReplace(string FilePath)
{
MemoryStream mem = new MemoryStream(System.IO.File.ReadAllBytes(FilePath));
using (WordprocessingDocument wordDoc = WordprocessingDocument.Open(mem, true))
{
string docText = null;
using (StreamReader sr = new StreamReader(wordDoc.MainDocumentPart.GetStream()))
{
docText = sr.ReadToEnd();
}
Regex regexText = new Regex("Hello world!");
docText = regexText.Replace(docText, "Hi Everyone!");
//Instead using this code below to write text back the original file. I write new string back to memory stream and return to a stream download file
//using (StreamWriter sw = new //StreamWriter(wordDoc.MainDocumentPart.GetStream(FileMode.Create)))
//{
// sw.Write(docText);
//}
using (StreamWriter sw = new StreamWriter(mem))
{
sw.Write(docText);
}
}
mem.Seek(0, SeekOrigin.Begin);
return File(mem, "application/octet-stream","download.docx"); //Return to download file
}
Please suggest me any solutions instead read a text from a word file and replace those expected pattern text then write data back to the original file. Are there any solutions replace text with WordprocessingDocument libary? How can I return to memory stream with validation docx file format?
The approach you are taking is not correct. If, by chance, the pattern you are searching for matches some Open XML markup, you will corrupt the document. If the text you are searching for is split over multiple runs, your search/replace code will not find the text and will not operate correctly. If you want to search and replace text in a WordprocessingML document, there is a fairly easy algorithm that you can use:
Break all runs into runs of a single
character. This includes runs that
have special characters such as a
line break, carriage return, or hard
tab.
It is then pretty easy to find a
set of runs that match the characters
in your search string.
Once you have identified a set of runs that match,
then you can replace that set of runs
with a newly created run (which has
the run properties of the run
containing the first character that
matched the search string).
After replacing the single-character runs
with a newly created run, you can
then consolidate adjacent runs with
identical formatting.
I've written a blog post and recorded a screen-cast that walks through this algorithm.
Blog post: http://openxmldeveloper.org/archive/2011/05/12/148357.aspx
Screen cast: http://www.youtube.com/watch?v=w128hJUu3GM
-Eric
string sourcepath = HttpContext.Server.MapPath("~/File/Form/s.docx");
string targetPath = HttpContext.Server.MapPath("~/File/ExportTempFile/" + DateTime.Now.ToOADate() + ".docx");
System.IO.File.Copy(sourcepath, targetPath, true);
using (WordprocessingDocument wordDocument = WordprocessingDocument.Open(targetPath, true))
{
string docText = null;
using (StreamReader sr = new StreamReader(wordDocument.MainDocumentPart.GetStream()))
{
docText = sr.ReadToEnd();
}
Regex regexText = new Regex("Hello world!");
docText = regexText.Replace(docText, "Hi Everyone!");
byte[] byteArray = Encoding.UTF8.GetBytes(docText);
MemoryStream stream = new MemoryStream(byteArray);
wordDocument.MainDocumentPart.FeedData(stream);
}
MemoryStream mem = new MemoryStream(System.IO.File.ReadAllBytes(targetPath));
return File(mem, "application/octet-stream", "download.docx");
Writing directly to the word document stream will indeed corrupt it.
You should instead write to the MainDocumentPart stream, but you should first truncate it.
It looks like MainDocumentPart.FeedData(Stream sourceStream) method will do just that.
I haven't tested it but this should work.
public ActionResult SearchAndReplace(string FilePath)
{
MemoryStream mem = new MemoryStream(System.IO.File.ReadAllBytes(FilePath));
using (WordprocessingDocument wordDoc = WordprocessingDocument.Open(mem, true))
{
string docText = null;
using (StreamReader sr = new StreamReader(wordDoc.MainDocumentPart.GetStream()))
{
docText = sr.ReadToEnd();
}
Regex regexText = new Regex("Hello world!");
docText = regexText.Replace(docText, "Hi Everyone!");
using (MemoryStream ms = new MemoryStream())
{
using (StreamWriter sw = new StreamWriter(ms))
{
sw.Write(docText);
}
ms.Seek(0, SeekOrigin.Begin);
wordDoc.MainDocumentPart.FeedData(ms);
}
}
mem.Seek(0, SeekOrigin.Begin);
return File(mem, "application/octet-stream","download.docx"); //Return to download file
}