thanks for reading, my doubt is the following, im trying to get data from an xls file but it has to be done locally, without uploading the file, i have done something similiar with txts files and works perfectly :
Function Send(ByVal file As HttpPostedFileBase) As ActionResult
Dim line As String
Dim textreader As System.IO.StreamReader = New StreamReader(file.InputStream)
While Not textreader.EndOfStream
line = textreader.ReadLine()
ViewBag.line = line
End While
Return View("Index")
End Function
but i cant do the same to the excel file, first of all, because i cant use the streamreader, so when using this code i dont know how to specify the dir of my xls file
Dim oApp As Excel.Application = New Excel.Application
Dim oWB As Excel.Workbook
Dim oSheet As Excel.Worksheet
oWB = oApp.Workbooks.Open(file.inputstream) <-- HERE IS WHERE I GET (AN OBVIOUS) ERROR
does anybody knows how to open the file locally? thanks for reading :)
There are several ways of doing it, one of them is accessing the file "database style"
...
...
string filePath = string.Format("C:\\TEST\\{0}.xlsx", Guid.NewGuid().ToString());
var fileStream = File.Create(filePath);
input.CopyTo(file.InputStream);
fileStream.Close();
string cn = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" + filePath + ";Extended Properties=\"Excel 12.0;HDR=YES;\"";
string query = "SELECT * FROM SHEET_NAME";
conn= new OleDbConnection(cn);
conn.Open();
OleDbCommand woOleCommand = new OleDbCommand(query, conn);
DbDataReader result = woOleCommand.ExecuteReader();
// Read the DataReader...
...
So basically you query Sheets like tables, if they are indeed tables, this code might be what you're looking for.
On the other hand, if you still need to use automation, try something like this instead:
...
object missing = System.Reflection.Missing.Value;
wBook = (Excel._Workbook)xl.Workbooks.Open(filePath, false, false, missing, missing, missing, missing, missing, missing, missing, missing, missing, missing, missing, missing);
...
Reading InputStream
using (var fileStream = File.Create(filePath)) {
file.InputStream.CopyTo(fileStream);
}
// Now you got your stream on a file (filePath) so you can work with it.
Related
I am working on the server that receives a file stream uploaded by multipart uploader.
But I got an additional WebKitFormBoundary.
If I remove it manually, it will work. So I tried the following code:
var fileStream = File.Create(#"C:\Users\myname\Desktop\myimage.png");
stream sr = new streamReader(myStream);
string myText = sr.ReadToEnd();
string newText = myText.Substring(myText.IndexOf("‰")); // remove header
byte[] byteArray = Encoding.ASCII.GetBytes(newText);
MemoryStream data = new MemoryStream(byteArray);
data.CopyTo(filestream);
If I use the above way to convert it to string, remove boundary and convert back to stream
the first character "‰" will become "?"
(ie. So ‰PNG will become ?PNG and the file becomes not readable.)
Any suggestions?
Where could I possible got wrong?
Thanks
This drove me nuts. Finally understood that if you have access to the request, you can access just the contents (with no header) like this:
var provider = new MultipartMemoryStreamProvider();
await Request.Content.ReadAsMultipartAsync(provider);
var file = await provider.Contents[0].ReadAsStreamAsync();
Hope this helps you, or someone with the same issue.
I have got the same issue but after investigating several blogs with applied several solutions, I got final working one. Please follow below code approach to fix it.
MemoryStream memoryStream = new MemoryStream(File.ReadAllBytes(filePath));
StreamReader streamReader = new StreamReader(memoryStream, Encoding.Default, true);
memoryStream.Seek(0, SeekOrigin.Begin);
string fileString = streamReader.ReadToEnd();
string fileData = fileString.Substring(0, fileString.IndexOf("\r\n\r\n") + 4);
string finalData = Regex.Replace(fileString, fileData, "");
var fileDataArr = Regex.Split(fileData, "\r\n|\r|\n").ToList();
var resultData = Regex.Replace(finalData, fileDataArr[0] + "--", "");
byte[] buffer = Encoding.Default.GetBytes(resultData);
Steps:
Convert your filedata into memory stream which can be used to read file content.
Use StreamReader to read file content and remove webkitformBoundary Header with default Encoding format.
Code To remove first 4 lines including webkitformBoundary from Top.
Code to remove webkitformBoundary from Footer.
Convert the string into Byte Array with default encoding format to maintain the file Encoding format.
Example:
WebKitFormBoundary Header
------WebKitFormBoundaryL1NUALe5NDrNt9S0 <br/>
Content-Disposition: form-data; name="userfile"; filename="BRtestfile1.pdf" <br/>
Content-Type: application/pdf <br/>
WebKitFormBoundary Footer
------WebKitFormBoundaryL1NUALe5NDrNt9S0-- <br/>
Currently, I can upload files(exist) with Grails's RestBuilder.
However, I want to upload a file without creating a file .
I want to create binary data (= Text File) in a program and send it directly
Is it possible?
RestBuilder rest = new RestBuilder()
RestResponse resp = rest.post(url){
contentType("multipart/form-data")
setProperty("dataFile",[filePath])// <- it can
setProperty("dataFile",[ byte[] or inputStream() or String ? ])// <- Is it possible?
}
'''
I'm sure you figured this out already, but you can just use a String reference or a byte[] just as you can use File instances for the multipart request using RestBuilder. It should 'just work' e.g.
RestBuilder rest = new RestBuilder()
RestResponse response = rest.post(url) {
contentType 'multipart/form-data'
stringPart = 'hello' // String
bytePart = '68656c6c6f'.decode64() // byte[]
filePart = new File('/path/to/file.jpg') // File
}
As each user runs through my application I hold their data and dump it into a report as follows, which at the end is created into a pdf document and is later automatically downloaded on the users side(client-side). I now want to attach this document to an email and have it forwarded to them. This is where I have troubles with the attachment.
Code as follows:
ReportDocument rd = new ReportDocument();
rd.Load(Path.Combine(Server.MapPath("~/Reports/PP_RentalAgreement.rpt")));
rd.SetParameterValue("rent_agree_no", _1);
rd.SetParameterValue("r_initial", _2);
rd.SetParameterValue("r_f_name", _3);
rd.SetParameterValue("r_l_name", _4);
rd.SetParameterValue("r_id_no", _5);
rd.SetParameterValue("r_lic_no", _6);
rd.SetParameterValue("r_tel", _7);
rd.SetParameterValue("r_cell", _8);
rd.SetParameterValue("r_fax", _9);
Response.Buffer = false;
Response.ClearContent();
Response.ClearHeaders();
Stream st = rd.ExportToStream(CrystalDecisions.Shared.ExportFormatType.PortableDocFormat);
st.Seek(0, SeekOrigin.Begin);
if (ModelState.IsValid)
{
var m_message = new MailMessage();
m_message.To.Add(new MailAddress("JoeSoap#TextMail.com"));
m_message.Subject = "Pink Panther - Invoice";
m_message.Attachments.Add(new Attachment(st, "application/pdf", "Invoice.pdf"));
using (var smtp = new SmtpClient())
{
await smtp.SendMailAsync(m_message);
return RedirectToAction("Index");
}
}
I am getting an error on this line : m_message.Attachments.Add(new Attachment(st, "application/pdf", "Invoice.pdf")); saying The specified content type is invalid.
Someone suggested to me that I should specify a path however I am not actually saving this file anywhere
How am I able to allow the file to be attached and send it to the recipient?
The System.Net.Mail.Attachment class constructor with 3 overloads consist of these parameters:
public Attachment(System.IO.Stream contentStream, string name, string mediaType)
Hence, you're assigning name and content type in reversed order, which causing invalid content type problem at this code:
m_message.Attachments.Add(new Attachment(st, "application/pdf", "Invoice.pdf"));
The correct way is putting the file name as second argument like example below:
m_message.Attachments.Add(new Attachment(st, "Invoice.pdf", "application/pdf"));
Or using MediaTypeNames for content type setting:
m_message.Attachments.Add(new Attachment(st, "Invoice.pdf", MediaTypeNames.Application.Pdf));
I'm trying to use the Google Machine Learning API and I'm facing two problems.
In the API explorer I put the correct information and I get a response error:
Code 200
"error": "Missing \"instances\" field in request body: {\n \"httpBody\": \n
{\n \"data\": \"\\"instances\\" : \\"teste\\"\",\n
\"contentType\": \"application/json\"\n }\n}"
The request find my model (if I change the value in field name I get another error) but don't understand my json. That's the json:
{"instances" : [{"key":"0", "image_bytes": {"b64": "mybase64"} }]}
When I do the predict on the command line using gcloud, I get no errors and everything seems ok. The Json that I was create for gcloud is a little bit different:
{"key":"0", "image_bytes": {"b64": "mybase64"} }
I already tryied that one in the API explorer and no success.
So, I decided to use the .Net Api to try the predict and I get other situation: The Response is Empty (???).
Here is my code:
'get the service credential that I created
Dim credential = Await GetCredential()
Dim myService As New CloudMachineLearningEngineService(New BaseClientService.Initializer() With {
.ApplicationName = "my Project Name (Is That It???)",
.ApiKey = "my API Key",
.HttpClientInitializer = credential
})
Dim myBase64 As String = GetBase64("my image path to convert into a base64 String")
Dim myJsonRequest As String = "{""instances"" : [{""key"":""0"", ""image_bytes"": {""b64"": """ + myBase64 + """}}]}"
Dim myRequest = New GoogleCloudMlV1PredictRequest With {
.HttpBody = New GoogleApiHttpBody With {.Data = myJsonRequest,
.ContentType = "application/json"
}
}
'If I change the model name I get error
Dim myPredictRequest = myService.Projects.Predict(myRequest, "projects/myProject/models/myModel/versions/v1")
myPredictRequest.AccessToken = credential.Token.AccessToken
myPredictRequest.OauthToken = credential.Token.AccessToken
myPredictRequest.Key = "my API Key
'Execute the request
Dim myResponse = myPredictRequest.Execute()
'at this point, myResponse is Empty (myResponse.ContentType Is Nothing, myResponse.Data Is Nothing And myResponse.ETag Is Nothing)
If I change the model name I get a error informing that my model was not found, so my credentials are right.
I don't know what I'm doing wrong. Someboby can help with any of this issues?
Thanks!
UPDATE: --------------------------
I changed this Execute Command:
Dim myResponse = myPredictRequest.Execute()
To This One:
Dim s = StreamToString(myPredictRequest.ExecuteAsStream())
and Now I can get the same error with .Net API and google developers interface (Missing instances field...).
So If someboby just Know what is wrong with my Json request, It will help a lot.
The JSON you put in the API explorer is indeed correct (assuming, of course, your model has inputs key and image_bytes). This appears to be a bug with the explorer I will report.
The reason you are getting the error you are in the .NET code is because you are using an .HttpBody field. This code:
Dim myJsonRequest As String = "{""instances"" : [{""key"":""0"", ""image_bytes"": {""b64"": """ + myBase64 + """}}]}"
Dim myRequest = New GoogleCloudMlV1PredictRequest With {
.HttpBody = New GoogleApiHttpBody With {.Data = myJsonRequest,
.ContentType = "application/json"
}
}
Will produce a JSON request that looks like this:
{
"httpBody": {
"data": "{\"instances\" : [{\"key\":\"0\", \"image_bytes\": {\"b64\": \"mybase64\"} }]}",
"contentType": "application\/json"
}
}
When what you really need is:
{"instances" : [{"key":"0", "image_bytes": {"b64": "mybase64"} }]}
Hence the error message you see.
I don't know how to generate the correct response using the .NET library; based on the Python example in the docs, I would guess:
Dim myJsonRequest As String = "{""instances"" : [{""key"":""0"", ""image_bytes"": {""b64"": """ + myBase64 + """}}]}"
Dim myPredictRequest = myService.Projects.Predict(myJsonRequest, "projects/myProject/models/myModel/versions/v1")
But I don't have a good way of testing that. For reference, the Python equivalent is:
response = service.projects().predict(
name=name,
body=myJsonRequest
).execute()
I solved the problem with .Net API.
I created two new classes Inherits the Google API's classes.
Something like that:
Imports Google.Apis.CloudMachineLearningEngine.v1.Data
Imports Newtonsoft.Json
Public Class myGoogleCloudMlV1PredictRequest
Inherits GoogleCloudMlV1PredictRequest
<JsonProperty("instances")>
Public Property MyHttpBody As List(Of myGoogleApiHttpBody)
End Class
Imports Google.Apis.CloudMachineLearningEngine.v1.Data
Imports Newtonsoft.Json
Public Class myGoogleApiHttpBody
Inherits GoogleApiHttpBody
<JsonProperty("image_bytes")>
Public Property MyData As image_byte
<JsonProperty("key")>
Public Property key As String
End Class
So, in my original code I change this part:
Dim myBase64 As String = GetBase64("my_image_path_to_convert_into_a _base64_String")
Dim myJsonRequest As String = "{""instances"" : [{""key"":""0"", ""image_bytes"": {""b64"": """ + myBase64 + """}}]}"
Dim myRequest = New GoogleCloudMlV1PredictRequest With {
.HttpBody = New GoogleApiHttpBody With {.Data = myJsonRequest,
.ContentType = "application/json"
}
}
For this one:
Dim myBase64 As String = GetBase64("my_image_path_to_convert_into_a _base64_String")
Dim myRequest = New myGoogleCloudMlV1PredictRequest With {
.MyHttpBody = New List(Of myGoogleApiHttpBody)()
}
Dim item As myGoogleApiHttpBody = New myGoogleApiHttpBody With {
.key = "0",
.MyData = New image_byte With {
.b64 = myBase64
}
}
myRequest.MyHttpBody.Add(item)
And voilá, It's working!
Thanks for everyone!!
Github issue #1068 shows two work-arounds for this problem.
In summary, use service.ModifyRequest to insert the raw JSON content.
Or use service.HttpClient.PostAsync(...) directly.
I am generating a report in an MVC project. The user has the option of getting the report in either .pdf format or .xls
I am using Aspose.Cells for the Excel file generation. The ActionResult method below is called.
[HttpGet]
public ActionResult GenerateReport(string format, string filterDate = "")
{
//Processing occurs here to get the appropriate info from Db.
var fileFormat = format.ToUpper() == "PDF" ? Format.Pdf : Format.Csv;
var contentType = fileFormat == Format.Pdf ? "application/pdf" : "application/vnd.ms-excel";
var makePdf = fileFormat == Format.Pdf;
var fileContents = register.GetReport(makePdf, filterDate);
return File(fileContents, contentType, "Report");
}
register.GetReport() merely determines if GetExcelVersion() or GetPdfVersion() is called.
private void GetExcelVersion(MemoryStream stream, string name, string dateRequested = "")
{
var license = new Aspose.Cells.License();
license.SetLicense("Aspose.Total.lic");
var workbook = new Workbook();
var worksheet = workbook.Worksheets[0];
var cells = worksheet.Cells;
//writes out the appropriate information to the excel spreadsheet here
workbook.Save(stream, new XlsSaveOptions(Aspose.Cells.SaveFormat.Excel97To2003));
}
This works a charm in Firefox and IE10 but when testing on IE8 I receive the following alert from Excel:-
The File you are trying to open 'XXXXX', is in a different format than specified by the file extension. Verify that the file is not corrupted and is from a trusted source before opening the file. Do you want to open the file now? Yes/No
Any ideas on what I am doing wrong?
Cheers!
As Saqib Razzaq mentioned in the comments above. Turn off compatibility mode as mentioned here