This is about sending/receiving contents of an XML file to/from Azure Service Message Queue using TopicClient in C#.
I am sending contents of a XML file as string, I can see the message on the Azure Queue and can even read its contents properly, so everything works fine when I send a plain text XML file.
But, due to data restrictions on the incoming message on the queue, I had to compress the file before sending it, I am using the C#'s DeflateStream to compress the contents of the file and writing it back to a file. On the receiving end, I am able to read the contents of the file but its not the same as what was sent.
I suspect this is has got something to do with the encoding. Could you please guide me on what I am missing? Thanks in advance.
Sender
public string Compress(FileInfo XMLFile) {
using(FileStream originalFileStream = file.OpenRead()) {
if ((File.GetAttributes(file.FullName) & FileAttributes.Hidden) !=
FileAttributes.Hidden & file.Extension != ".cmp") {
using(FileStream compressedFileStream = File.Create(file.FullName + ".cmp")) {
using(DeflateStream compressionStream = new DeflateStream(compressedFileStream, CompressionMode.Compress)) {
originalFileStream.CopyTo(compressionStream);
}
}
FileInfo info = new FileInfo(directoryPath + "\\" + file.Name + ".cmp");
Console.WriteLine("Compressed {0} from {1} to {2} bytes.", file.Name, file.Length, info.Length);
}
}
return info.FullName;
}
// snippet from the send method
FileInfo XMLfile = new FileInfo(XMLFilePath);
string CompressedXMLFilePath = Compress(XMLfile);
TopicClient myTopicClient = TopicClient.CreateFromConnectionString(AzureConnectionString);
string toSend = File.ReadAllText(CompressedXMLFilePath); // read contents of file compressed with DeflateStream.
myTopicClient.Send(new BrokeredMessage(toSend));
Receiver
var subClient = SubscriptionClient.CreateFromConnectionString(_serviceBusConn, _serviceBustopic, "<subscription name>");
subClient.OnMessage(m =>
{
Console.WriteLine(m.GetBody<string>());
});
Related
I am trying to detect an encrypted attachment using ICSharpCode.SharpZipLib,
but the code breaks while debugging on this line:
FileStream fileStreamIn = new FileStream(attachtype, FileMode.Open, FileAccess.Read);
Is there any other way through which I can get Outlook attachment and scan for encryption?
if (attachments.Count != 0)
{
for (int i = 1; i <= mail.Attachments.Count; i++)
{
String attachtype = mail.Attachments[i].FileName.ToLower();
if (extensionsArray.Any(attachtype.Contains))
{
FileStream fileStreamIn = new FileStream(attachtype, FileMode.Open, FileAccess.Read);
ZipInputStream zipInStream = new ZipInputStream(fileStreamIn);
ZipEntry entry = zipInStream.GetNextEntry();
MessageBox.Show("IsCrypted: " + entry.IsCrypted);
}
}
}
I'm assuming you are using Microsoft.Office.Interop.Outlook namespaces.
According to the MSDN the Filename property does the following (source):
Returns a String (string in C#) representing the file name of the
attachment. Read-only.
So the value is only the name of the file, not the location (it does not exist on disk as a accessible file). When supplying just the filaneme into a FileStream it will attempt to open a file with that name in the local directory (which probably does not exist).
It seems from the documentation you'll need to store it using the SaveAsFile method (source) into a temporary file and load a FileStream from that.
So something like:
// Location to store file so we can access the data.
var tempFile = Path.GetTempFileName();
try {
// Save attachment into our file
mail.Attachments[i].SaveToFile(tempFile);
using(var stream = File.OpenRead(tempFile)) {
// Do stuff
}
} finally {
// Cleanup the temp file
File.Delete(tempFile);
}
I am working on code in C#,but not going through on thing that is I have saved some .eml file on my disk now I am parsing each eml file and creating a new mail adding the eml file data to the new mail but I am unable to attach the attachments present in the .eml file to the new mail , can anybody please help?
I am using the follwing code but it shows the error ex = {"The process cannot access the file because it is being used by another process.\r\n":null}
foreach (CDO.IBodyPart attach in msg.Attachments)
{
i++;
string filenm = "C:\\mail_automation\\attachments\\xyz" + i +".eml";
if (File.Exists(filenm))
{
string fn = attach.FileName;
attach.SaveToFile("C:\\mail_automation\\attachments\\xyz" + i + ".eml");
Attachment data = new Attachment(filenm);
mailMessage.Attachments.Add(data);
}
else
{
File.Create(filenm);
string fn = attach.FileName;
attach.SaveToFile("C:\\mail_automation\\attachments\\xyz" + i + ".eml");
Attachment data = new Attachment(filenm);
mailMessage.Attachments.Add(data);
}
You have to extract the attachments and save them to disk first, then fetch it again into the new mail.
Code example here
MailMessage message = new MailMessage();
MemoryStream ms = new MemoryStream(); //store the mail into this ms 'memory stream'
ms.Position = 0;
message.Attachments.Add(new Attachment(ms, attachmentName));
I generate a PDF file, save it on the server:
var bytes = ms.ToArray();
. . .
String fileFullpath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.DesktopDirectory), pdfFileName);
. . .
File.WriteAllBytes(fileFullpath, bytes);
...and then save it into a Sharepoint Document Library, and send it as an email attachment to the person who generated the file:
SavePDFToDocumentLibrary(fileFullpath);
String from = GetFromEmailID();
String to = GetUserEmail();
String subjLine = String.Format("The PDF file you generated ({0})", pdfFileName);
String body = String.Format("The Direct Pay PDF file you generated ({0}) is attached.", pdfFileName);
SendEmailWithAttachment(fileFullpath, from, to, subjLine, body);
// Now that it has been put in a Document Library and emailed, delete the file that was saved locally
File.Delete(fileFullpath);
...at which point, I no longer need the file I saved to disk on the server, and so, as shown in the last line above, attempt to delete it.
However, it doesn't work. The now-redundant file is still in the place where it was saved.
Why, and how can I get it to understand that "Delete" really means "delete"?
UPDATE
Here are the methods Scott wanted to see:
// This works; got it from Henry Zucchini's answer at http://stackoverflow.com/questions/468469/how-do-you-upload-a-file-to-a-document-library-in-sharepoint
private void SavePDFToDocumentLibrary(String fullpath)
{
String fileToUpload = fullpath;
String sharePointSite = siteUrl;
String documentLibraryName = "DirectPayPDFForms";
using (SPSite oSite = new SPSite(sharePointSite))
{
using (SPWeb oWeb = oSite.OpenWeb())
{
if (!System.IO.File.Exists(fileToUpload))
throw new FileNotFoundException("File not found.", fileToUpload);
SPFolder doclib = oWeb.Folders[documentLibraryName];
// Prepare to upload
Boolean replaceExistingFiles = true;
String fileName = System.IO.Path.GetFileName(fileToUpload);
FileStream fileStream = File.OpenRead(fileToUpload);
// Upload document
SPFile spfile = doclib.Files.Add(fileName, fileStream, replaceExistingFiles);
// Commit
doclib.Update();
}
}
}
// This is adapted from https://msdn.microsoft.com/en-us/library/system.net.mail.mailmessage(v=vs.90).aspx
public static void SendEmailWithAttachment(string fileToMail, String from, String to, String subj, String body)
{
String server = GetSMTPHostName(); //"468802-DEV-SPWF"; // change this to prod when go live, or programatically assign?
// Specify the file to be attached and sent.
string file = fileToMail;
// Create a message and set up the recipients.
MailMessage message = new MailMessage(
from,
to,
subj,
body);
// Create the file attachment for this e-mail message.
Attachment data = new Attachment(file, MediaTypeNames.Application.Octet);
// Add time stamp information for the file.
ContentDisposition disposition = data.ContentDisposition;
disposition.CreationDate = System.IO.File.GetCreationTime(file);
disposition.ModificationDate = System.IO.File.GetLastWriteTime(file);
disposition.ReadDate = System.IO.File.GetLastAccessTime(file);
// Add the file attachment to this e-mail message.
message.Attachments.Add(data);
//Send the message.
SmtpClient client = new SmtpClient(server);
// Add credentials if the SMTP server requires them.
client.Credentials = CredentialCache.DefaultNetworkCredentials;
try
{
client.Send(message);
}
catch (Exception ex)
{
Console.WriteLine("Exception caught in CreateMessageWithAttachment(): {0}", ex.ToString());
}
// Display the values in the ContentDisposition for the attachment.
// May not need/want this section
ContentDisposition cd = data.ContentDisposition;
Console.WriteLine("Content disposition");
Console.WriteLine(cd.ToString());
Console.WriteLine("File {0}", cd.FileName);
Console.WriteLine("Size {0}", cd.Size);
Console.WriteLine("Creation {0}", cd.CreationDate);
Console.WriteLine("Modification {0}", cd.ModificationDate);
Console.WriteLine("Read {0}", cd.ReadDate);
Console.WriteLine("Inline {0}", cd.Inline);
Console.WriteLine("Parameters: {0}", cd.Parameters.Count);
foreach (DictionaryEntry d in cd.Parameters)
{
Console.WriteLine("{0} = {1}", d.Key, d.Value);
}
// </ May not need/want this section
data.Dispose();
}
UPDATE 2
I see when stepping through it, after adding this test:
if (File.Exists(fileFullpath))
{
File.Delete(fileFullpath);
}
...that there is an exception after all, in the IOException catch block:
The process cannot access the file 'C:\Users\TEMP.SP.018\Desktop\DirectPayDynamic_2015Jul28_19_02_clayshan_0.pdf' because it is being used by another process.
So how is one of the other methods holding onto it? ISTM that SavePDFToDocumentLibrary() is safe, because it uses using blocks.
Is data.Dispose(); in SendEmailWithAttachment() not enough? Do I need to explicitly call close there, or what?
UPDATE 3
I added "message.Dispose();" just prior to "data.Dispose();" in SendEmailWithAttachment(), but it made no difference.
Try disposing the file stream used in SavePDFToDocumentLibrary like so:
using (FileStream fileStream = File.OpenRead(fileToUpload))
{
...
}
How come this code writes an empty file at given location?
No error messages.
// upload file
WebRequest upload = WebRequest.Create(ftp + path + "/" + file);
upload.Method = WebRequestMethods.Ftp.UploadFile;
upload.Credentials = new NetworkCredential(username, password);
String filePath = HttpContext.Current.Server.MapPath("~/temp/" + file); // path to file to upload
Stream myReadStream = new FileStream(filePath, FileMode.Create); // stream that can read binary data
BinaryWriter myStreamWriter = new BinaryWriter(upload.GetRequestStream()); // writer that can write the binary data to the FTP server
while (myReadStream.ReadByte() != -1)
{
myStreamWriter.Write(myReadStream.ReadByte());
}
myStreamWriter.Close();
myReadStream.Close();
Removing the while loop creates a file 4byte big and corrupt so I guess I cant get in the while loop like this.
You should call upload.GetResponse() after myStreamWriter closed.
PS: In the while you write ONE time for every TWO times read, is it really you want?
I have a WCF service up and running which saves a file to my server. I have tested this by sending a .txt file and a .xls file. The size of the .xls file is 90kb.
Now I have a zipped file .gz that is only 70KB in size but when trying to complete this operation I get
The remote server returned an unexpected response: (400)
Bad Request.
When I have tried to search for this Bad Request most results lead to the fact that a large file is being sent and that I need to change the settings in the config file.
This is not the reason in my case as the .gz file is smaller than the .xls file!
Does anyone have any idea why this type of file cannot be sent the same as a text or Excel file???
Edit: Code Added
Here is the method to call the service
string name = "New Doc";
string file = #"C:/Users/Admin/Desktop/fileZipped.gz";
string ext = file.Split('.')[1];
Stream stream = File.OpenRead(file);
byte[] bytes = new byte[stream.Length];
stream.Read(bytes, 0, (int)stream.Length);
stream.Close();
var uploadFileServiceClient = new UploadFileServiceClient();
uploadFileServiceClient.UploadFile(name, bytes, ext);
And here is my service:
[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
public class UploadFileService : IUploadFileService
{
public bool UploadFile(string name, byte[] bytes, string extension)
{
string importDir = ConfigurationSettings.AppSettings["UploadFileDir"];
if (String.IsNullOrEmpty(importDir))
return false;
if (!Directory.Exists(importDir))
return false;
string outputFile = Path.Combine(importDir, Guid.NewGuid() + "." + extension);
string filename = outputFile.Split('\\')[2];
using (StreamWriter sw = new StreamWriter(outputFile))
{
sw.WriteLine(bytes);
sw.Flush();
sw.Close();
}
return true;
}
}
Like I say it works for text or Excel files.
IF there is no "filtering proxy" inbetween:
We had something similar and the solution turned out to setup the MIME type on client+server accordingly...