ASP Component to Send Arbitary Large File from Server to Client

This article was contributed by Shimon Pozzin.

Platform:

Windows NT 4.x SP4, ATL 2.x, MS Visual C++ 5.x, IIS 4.x

Purpose:

Demonstrate IResponse::BinaryWrite call from ATL component.

Description:

Writing some scripts in ASP (hey, this is not my job! :-) ) I came across the problem of sending the binary file from server to client.

How to use:

Attached project is full source code of the component, sample ASP file, sample HTM file and a sample GIF file. Of course, the file may be any binary file, but you should be careful about correct MIME type of the file being transferred. Source is free for distribution, modification etc.

Full annoying comments (aka how it was built):

IResponse::BinaryWrite() expects as a parameter a variant, containing safearray of type VT_ARRAY | VT_UI1 (array of unsigned char[s]) This project was build using standard ATL wizard with default options. Then, ASP object was inserted into the project (what else could you add to the project that must work in ASP script?!) Finally, one simple method, called GetFile() was added to the interface of the ASP object as follows:



#define RETURN { hr = E_FAIL; goto Cleanup; }	// don't kill me! Look at last examples of MS
						// under http://www.microsoft.com/data/xml
						// You can't catch me! :-)
STDMETHODIMP CGetFile::GetFile(VARIANT vFileName)
{
	_variant_t	vReturnBuffer;
	LPSAFEARRAY	psaFile;
	HANDLE		hFile;
	DWORD		dwSizeOfFile;
	DWORD		dwNumberOfBytesRead;
	BOOL		bResult;
	unsigned char	*pReturnBuffer = NULL;
	long		k;
	HRESULT		hr = S_OK;

	// Create file in this case only OPENS an existing file (or fails
	// if the file does not exist!)
	hFile = ::CreateFile(
			vFileName.bstrVal,		// name of the file
			GENERIC_READ,			// desired access
			FILE_SHARE_READ,		// shared access
			NULL,				// security attributes
			OPEN_EXISTING,			// creation disposition - open only if existing!
			FILE_FLAG_SEQUENTIAL_SCAN,	// flag attributes
			NULL );
		
	if( hFile == INVALID_HANDLE_VALUE )
	{
		return E_FAIL;
	}

	dwSizeOfFile = ::GetFileSize( hFile, NULL );
	if (dwSizeOfFile == 0xFFFFFFFF)
	{
		return E_FAIL;
	}

	try
	{
		pReturnBuffer = new unsigned char[dwSizeOfFile];
	}
	catch( std::bad_alloc& )
	{
		return E_FAIL;
	}

	// Get the binary content of the file
	bResult = ::ReadFile( hFile, pReturnBuffer, dwSizeOfFile, &dwNumberOfBytesRead, NULL );
	if( FALSE == bResult )
	{
		RETURN(E_FAIL);
	}

	psaFile = ::SafeArrayCreateVector( VT_UI1 /*unsigned char*/, 0, dwSizeOfFile );
		
	if( !psaFile )
	{
		RETURN(E_FAIL);
	}

	// Fill in the SAFEARRAY with the binary content of the file
	for( k = 0; k 
        <
         (int) dwSizeOfFile; k++ )
	{
		if( FAILED(::SafeArrayPutElement( psaFile, &k, &pReturnBuffer[k] )) )
		{
			RETURN(E_FAIL);
		}
	}

	vReturnBuffer.vt = VT_ARRAY | VT_UI1;
	V_ARRAY(&vReturnBuffer) = psaFile;

	m_piResponse->BinaryWrite(vReturnBuffer);

Cleanup:

	if( pReturnBuffer )
		delete [] pReturnBuffer;

	return SUCCEEDED(hr) ? S_OK : E_FAIL;
}
 from WWW.VCKBASE.COM

As you see, the idea is simple: to read the binary content of the file, to pack it into safearray and then to pass as a parameter to IResponse::BinaryWrite(). The process is pretty straightforward

Download source and demo project - 62 KB



To test the demo project you have to put aspfile.asp, aspfile.dll and canflag.gif in the same directory, say, /test. Then register component (from command prompt issue: regsvr32 aspfile.dll.) Then create a virtual directory without read permissions pointing to /test. Create another virtual directory, called, say, /test1. Put aspfile.htm file into this directory. Original demo project is made so that all files are in the same virtual directory, so you have to change the path in aspfile.asp to real virtual directory where aspfile.asp file is located (e.g. "/test/aspfile.asp") That's it. Open a browser, type URL http://localhost/test1/aspfile.htm and observe wonderful canadian flag!

You may ask: "Why would I bother with script if I can simply point my URL to that path and to download the file like I did a million times?"
Well, sometimes you cannot. The main reason for that is execute-only permissions for the directory where the file is located. In this case you will not be able to get the file (browser will return an error).
This is when you should remember this handy component. You may send any binary file from server to client.
Response object of ASP contains a method called BinaryWrite. We have one problem, however. This method is not documented well. And there are no examples how to use it. This is why I decided to fill this gap.
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值