File Upload

File Upload

am 12.06.2007 00:16:45 von rn5a

I came across this article titled Pure ASP File Upload at
http://www.asp101.com/articles/jacob/scriptupload.asp & tried it on my
local IIS5.1. Intranet server & it worked. I saved the necessary data
in a MS-Access database file (& not in the hard disk).

Can someone please tell me how do I mail the uploaded file as an
attachment using CDO.MESSAGE?

I tried getting in touch with Jacob, author of the article at the
above URL, by e-mailing him at his e-mail id (which is given in the
article) but unfortunately, the mail bounced back saying delivery
failed!

Thanks

Re: File Upload

am 12.06.2007 01:34:53 von Dave Anderson

rn5a@rediffmail.com wrote:
> I came across this article titled Pure ASP File Upload at
> http://www.asp101.com/articles/jacob/scriptupload.asp & tried
> it on my local IIS5.1. Intranet server & it worked. I saved the
> necessary data in a MS-Access database file (& not in the hard
> disk).
>
> Can someone please tell me how do I mail the uploaded file as
> an attachment using CDO.MESSAGE?

This is fairly simple. You need an ASP script that will stream the file to a
browser, based on some key to the DB record. Then you construct a URL for
use in the AddAttachment method of the CDO.Message object.

IMessage.AddAttachment(URL,[UserName],[Password]) ...

"The URL prefixes supported in the URL parameter are file://,
ftp://, http://, and https://. The default prefix is file://.
This facilitates designation of paths starting with drive
letters and of universal naming convention (UNC) paths."

http://msdn2.microsoft.com/en-us/library/ms526983.aspx


To give you an example, here is a segment of code from a feedback form I
use. In it, I call a stored procedure that returns a list of files to be
attached to the message, then makes successive calls to AddAttachment():

for (CN.File_ListByRequest(GUID,"Feedback","Attachment",RS); !RS.EOF;
RS.MoveNext())
MSG.AddAttachment([My script URL] + "?RecordID=" +
RS.Fields("RecordID").Value)

Those calls, in turn, trigger this script (excerpted, of course):

var RecordID = Request.QueryString("RecordID").Item,
CN = Server.CreateObject("ADODB.Connection"),
RS = Server.CreateObject("ADODB.Recordset")
CN.Open(*** my connection string ***)
CN.File_Retrieve(RecordID,RS)
if (!RS.EOF) {
Response.AddHeader("Content-Length",RS.Fields("FileSize").Va lue)
Response.AddHeader("Content-Disposition","inline; filename=" +
RS.Fields("FileName").Value + ";")
Response.ContentType = RS.Fields("ContentType").Value
Response.BinaryWrite(RS.Fields("Data").Value)
}
RS.Close()
CN.Close()

As you may have guessed, these are JScript examples.




--
Dave Anderson

Unsolicited commercial email will be read at a cost of $500 per message. Use
of this email address implies consent to these terms.

Re: File Upload

am 13.06.2007 10:59:57 von Anthony Jones

"Dave Anderson" wrote in message
news:%23GzmdEIrHHA.4132@TK2MSFTNGP05.phx.gbl...
> rn5a@rediffmail.com wrote:
> > I came across this article titled Pure ASP File Upload at
> > http://www.asp101.com/articles/jacob/scriptupload.asp & tried
> > it on my local IIS5.1. Intranet server & it worked. I saved the
> > necessary data in a MS-Access database file (& not in the hard
> > disk).
> >
> > Can someone please tell me how do I mail the uploaded file as
> > an attachment using CDO.MESSAGE?
>
> This is fairly simple. You need an ASP script that will stream the file to
a
> browser, based on some key to the DB record. Then you construct a URL for
> use in the AddAttachment method of the CDO.Message object.
>
> IMessage.AddAttachment(URL,[UserName],[Password]) ...
>
> "The URL prefixes supported in the URL parameter are file://,
> ftp://, http://, and https://. The default prefix is file://.
> This facilitates designation of paths starting with drive
> letters and of universal naming convention (UNC) paths."
>
> http://msdn2.microsoft.com/en-us/library/ms526983.aspx
>
>
> To give you an example, here is a segment of code from a feedback form I
> use. In it, I call a stored procedure that returns a list of files to be
> attached to the message, then makes successive calls to AddAttachment():
>
> for (CN.File_ListByRequest(GUID,"Feedback","Attachment",RS); !RS.EOF;
> RS.MoveNext())
> MSG.AddAttachment([My script URL] + "?RecordID=" +
> RS.Fields("RecordID").Value)
>
> Those calls, in turn, trigger this script (excerpted, of course):
>
> var RecordID = Request.QueryString("RecordID").Item,
> CN = Server.CreateObject("ADODB.Connection"),
> RS = Server.CreateObject("ADODB.Recordset")
> CN.Open(*** my connection string ***)
> CN.File_Retrieve(RecordID,RS)
> if (!RS.EOF) {
> Response.AddHeader("Content-Length",RS.Fields("FileSize").Va lue)
> Response.AddHeader("Content-Disposition","inline; filename=" +
> RS.Fields("FileName").Value + ";")
> Response.ContentType = RS.Fields("ContentType").Value
> Response.BinaryWrite(RS.Fields("Data").Value)
> }
> RS.Close()
> CN.Close()
>
> As you may have guessed, these are JScript examples.
>

Alternatively, instead of using a second request to the server, create the
attachment 'manually' like this:-

CN2 = Server.CreateObject("ADODB.Connection")
CN2.Open(*** my connection string ***)
RS2 = Server.CreateObject("ADODB.Recordset")

for (CN.File_ListByRequest(GUID,"Feedback","Attachment",RS); !RS.EOF;
RS.MoveNext())
{
CN2.File_Retrieve(RS.Fields("RecordID").Value, RS2)
if (!RS2.EOF) addAttachment(MSG, RS)
RS2.Close()
}
CN2.Close()

function addAttachment(voMsg, voRS)
{
var oPart = oMsg.Attachments.Add()
oPart.ContentMediaType = voRS.Fields("ContentType").Value
oPart.ContentTransferEncoding = "base64"
oPart.Fields("urn:schemas:mailheader:content-disposition") =
'attachment; filename="' + voRS.Fields("FileName").Value + '"'
oPart.Fields.Update()

var oStream = oPart.GetDecodedContentStream()

oStream.Write(voRS.Fields("Data").Value)
oStream.Flush()
}


Use of an HTTP URL in AddAttachment when running in ASP is undesirable since
CDO uses the WinINET api to perform the fetch. WinInet is not thread safe.
Self referencing URLs can also be a problem if used too often.

BTW, Don't use AddHeader to add a Content-Length header, IIS/ASP will handle
it so at best you're duplicating a header.

Re: File Upload

am 13.06.2007 18:26:12 von Dave Anderson

Anthony Jones wrote:
> Use of an HTTP URL in AddAttachment when running in ASP is
> undesirable since CDO uses the WinINET api to perform the
> fetch. WinInet is not thread safe. Self referencing URLs
> can also be a problem if used too often.

Nice explanation, Anthony. I have since incorporated this technique.



--
Dave Anderson

Unsolicited commercial email will be read at a cost of $500 per message. Use
of this email address implies consent to these terms.

Re: File Upload

am 27.07.2007 20:14:33 von Dave Anderson

On June 13, 2007, "Anthony Jones" wrote:
> function addAttachment(voMsg, voRS)
> {
> var oPart = oMsg.Attachments.Add()
> oPart.ContentMediaType = voRS.Fields("ContentType").Value
> oPart.ContentTransferEncoding = "base64"
> oPart.Fields("urn:schemas:mailheader:content-disposition") =
> 'attachment; filename="' + voRS.Fields("FileName").Value + '"'
> oPart.Fields.Update()
>
> var oStream = oPart.GetDecodedContentStream()
>
> oStream.Write(voRS.Fields("Data").Value)
> oStream.Flush()
> }
>
>
> Use of an HTTP URL in AddAttachment when running in ASP is undesirable
> since CDO uses the WinINET api to perform the fetch. WinInet is not
> thread safe. Self referencing URLs can also be a problem if used too
> often.

When certain file types are attached this way (HTML documents, for example),
the following error occurs:

ADODB.Connection error '800a0e79'
Operation is not allowed when the object is open.

The line in question is the Stream.Write() line.

How can this be overcome?


--
Dave Anderson

Unsolicited commercial email will be read at a cost of $500 per message. Use
of this email address implies consent to these terms.

Re: File Upload

am 27.07.2007 23:44:57 von Anthony Jones

"Dave Anderson" wrote in message
news:%23Hd98nH0HHA.2484@TK2MSFTNGP06.phx.gbl...
> On June 13, 2007, "Anthony Jones" wrote:
> > function addAttachment(voMsg, voRS)
> > {
> > var oPart = oMsg.Attachments.Add()
> > oPart.ContentMediaType = voRS.Fields("ContentType").Value
> > oPart.ContentTransferEncoding = "base64"
> > oPart.Fields("urn:schemas:mailheader:content-disposition") =
> > 'attachment; filename="' + voRS.Fields("FileName").Value + '"'
> > oPart.Fields.Update()
> >
> > var oStream = oPart.GetDecodedContentStream()
> >
> > oStream.Write(voRS.Fields("Data").Value)
> > oStream.Flush()
> > }
> >
> >
> > Use of an HTTP URL in AddAttachment when running in ASP is undesirable
> > since CDO uses the WinINET api to perform the fetch. WinInet is not
> > thread safe. Self referencing URLs can also be a problem if used too
> > often.
>
> When certain file types are attached this way (HTML documents, for
example),
> the following error occurs:
>
> ADODB.Connection error '800a0e79'
> Operation is not allowed when the object is open.
>
> The line in question is the Stream.Write() line.
>
> How can this be overcome?
>

Strange I've never seen that before in this context.

First experiment would be to split the stream write line:-

Dim fieldValue
fieldValue = voRS.Fields("Data").Value
oStream.Write(fieldValue)

That would highlight which of the two ADODB components the error is coming
from but thats just to ensure we're not chasing down the wrong path because
its almost certain the error is a result of accessing the value of the data
field.

The only reason I can guess at for this error is that for some reason
accessing the field is asking the connection to retrieve another stream of
data before its finished with the current one. I'd make sure the recordset
openned is a forward only recordset, that the Data field is the last field
in the field list and that consuming the data field's contents is the last
thing I do with that record before moving on.

The only time I've had CDO object to this approach is when trying to attach
another eml in which case the content type is message/rfc822, it refuses to
use base64 encoding and requires a text based encoding. Hence another
clutching a straws exercise might be to see if a failing attachment works if
the content type is set to application/octet-stream. However I honest don't
think that is the problem.


--
Anthony Jones - MVP ASP/ASP.NET

Re: File Upload

am 30.07.2007 18:16:28 von Dave Anderson

"Anthony Jones" wrote:
>> The line in question is the Stream.Write() line.
>
> First experiment would be to split the stream write line:-
>
> Dim fieldValue
> fieldValue = voRS.Fields("Data").Value
> oStream.Write(fieldValue)

I should have been more clear. I have already isolated it to Stream.Write()

> The only time I've had CDO object to this approach is when trying to
> attach another eml in which case the content type is message/rfc822,
> it refuses to use base64 encoding and requires a text based encoding.
> Hence another clutching a straws exercise might be to see if a failing
> attachment works if the content type is set to application/octet-stream.
> However I honest don't think that is the problem.

Either way I look at it, I have a problem. I can attempt to attach files
with Message.Attachments.Add() and streams, then start over with
Message.AddAttachment() if it fails, but that isn't a very satisfying
compromise.



--
Dave Anderson

Unsolicited commercial email will be read at a cost of $500 per message. Use
of this email address implies consent to these terms.

Re: File Upload

am 30.07.2007 22:55:35 von Anthony Jones

"Dave Anderson" wrote in message
news:Oa9E9Ts0HHA.5408@TK2MSFTNGP02.phx.gbl...
> "Anthony Jones" wrote:
> >> The line in question is the Stream.Write() line.
> >
> > First experiment would be to split the stream write line:-
> >
> > Dim fieldValue
> > fieldValue = voRS.Fields("Data").Value
> > oStream.Write(fieldValue)
>
> I should have been more clear. I have already isolated it to
Stream.Write()
>
> > The only time I've had CDO object to this approach is when trying to
> > attach another eml in which case the content type is message/rfc822,
> > it refuses to use base64 encoding and requires a text based encoding.
> > Hence another clutching a straws exercise might be to see if a failing
> > attachment works if the content type is set to application/octet-stream.
> > However I honest don't think that is the problem.
>
> Either way I look at it, I have a problem. I can attempt to attach files
> with Message.Attachments.Add() and streams, then start over with
> Message.AddAttachment() if it fails, but that isn't a very satisfying
> compromise.
>
>

Is there a small(ish) repeatable re-production for this problem or is it
more random and intermittent?
I use the technique a lot although I'm not sure I've ever attached HTML
content. What other types of content gets it upset? It could be that CDO
treats HTML as a special case for some reason.

--
Anthony Jones - MVP ASP/ASP.NET

Re: File Upload

am 31.07.2007 00:53:12 von Dave Anderson

"Anthony Jones" wrote:
> Is there a small(ish) repeatable re-production for this problem or
> is it more random and intermittent?

Those are not mutually exclusive options, Anthony. It's not especially small
to create an architecture to insert files into a database and to extract
them upon form submission. But the symptoms do not appear to be random or
intermittent. I can repeat it at will.

> I use the technique a lot although I'm not sure I've ever attached
> HTML content. What other types of content gets it upset? It could
> be that CDO treats HTML as a special case for some reason.

It appears to happen for all .txt, .htm, .html, or .xml files. Change the
extension on any of them to .log or .asp, for example, and the same file
goes through without error.



--
Dave Anderson

Unsolicited commercial email will be read at a cost of $500 per message. Use
of this email address implies consent to these terms.

Re: File Upload

am 31.07.2007 01:10:45 von Dave Anderson

I wrote:
> It appears to happen for all .txt, .htm, .html, or .xml files. Change
> the extension on any of them to .log or .asp, for example, and the
> same file goes through without error.

You know, this got me thinking, so I looked in the database, and each of the
affected ContentType values were of the text/xxx variety. Recalling you
advice about Response.AddHeader (and some ancient memory in my head about
how Mac IE5 used to send resource forks along with uploads), I asked what
business it was of mine to tell the client how to handle the file. I removed
the Part.ContentMediaType assignment, and everything sailed through as
desired.

Seems fair, no?



--
Dave Anderson

Unsolicited commercial email will be read at a cost of $500 per message. Use
of this email address implies consent to these terms.

Re: File Upload

am 31.07.2007 11:48:15 von Anthony Jones

"Dave Anderson" wrote in message
news:udK5c7v0HHA.4184@TK2MSFTNGP06.phx.gbl...
> I wrote:
> > It appears to happen for all .txt, .htm, .html, or .xml files. Change
> > the extension on any of them to .log or .asp, for example, and the
> > same file goes through without error.
>
> You know, this got me thinking, so I looked in the database, and each of
the
> affected ContentType values were of the text/xxx variety. Recalling you
> advice about Response.AddHeader (and some ancient memory in my head about
> how Mac IE5 used to send resource forks along with uploads), I asked what
> business it was of mine to tell the client how to handle the file. I
removed
> the Part.ContentMediaType assignment, and everything sailed through as
> desired.
>
> Seems fair, no?
>

As long as the file extension of the filename in the content-disposition
matches the content of the body part the client ought to handle it ok.
Personally I would much prefer the more explicit Content-Type header be
present.

The error I get is "operation not allowed in this context". This is because
when the content type is a text type then the ADODB stream object returned
by DecodedContentStream is in text mode and therefore is expecting us to use
WriteText not Write. This allows the stream object to encode the text to
the character set being used by the message.

I missed it because I simplified my code a little too much in my example.
The actual code I use (which is a VB6 dll) is 'overloaded' and in addition
to an array of bytes it can also take a refererence to IStream. In the
latter case the ADODB stream object's default interface is by passed and its
IStream interface is used to copy from the input IStream. This also
bypasses the character encoding that ADODB stream would have wanted to do
for a text type but since the transfer encoding is base64 this doesn't cause
a problem in transfer and the resulting file extracted at the other end is
byte for byte identical to the source.

If the email charset is different from the charset used in the source file
this might be a problem when the client tries to view the attachment.


--
Anthony Jones - MVP ASP/ASP.NET