Opening a File saved in Blob Variable - APEX 21.2 - oracle-apex

I'm using ORA_EXCEL PL/SQL API to create custom Excel files. I have it set so that when clicking a button it calls a GENERATE_EXCEL_PROCESS via a page submit (tried both Processing and After Submit processing points) and builds the file and saves it to a Blob variable (confirmed file creation is working in separate test writing file to an Oracle Directory).
My goal is to generate the Excel file in PLSQL, save to a blob and then display a download dialog for users to save the excel file locally similarly to the native Download link that Classic reports allow you to turn on declaratively.
When run I get a weird APEX error, that I only found by turning Full Trace mode on in debugging. I've included the code below, but I do not know what it means to troubleshoot further. It looks like I get a response back of Blob looking at network tab in devtools.
PROCEDURE apex_file_download(
p_file_name VARCHAR2,
p_generated_file BLOB,
p_file_type VARCHAR2 DEFAULT 'EXCEL'
) IS
vcMimeType VARCHAR2(1000);
blob_file BLOB;
blob_size INTEGER;
BEGIN
CASE p_file_type
WHEN 'EXCEL' THEN
vcMimeType := 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet';
END CASE;
blob_file := p_generated_file;
-- Get BLOB size
blob_size := dbms_lob.getlength(blob_file);
-- Print content type header for MS Excel
owa_util.mime_header(vcMimeType, FALSE, NULL);
-- Put BLOB size header
htp.p('Content-length: '|| blob_size);
-- Set file name that will be suggested when download dialog appears
htp.p('Content-Disposition: attachment; filename="'||p_file_name||'"');
-- Close header
owa_util.http_header_close;
-- Download BLOB
wpg_docload.download_file(blob_file);
apex_application.stop_apex_engine;
EXCEPTION
WHEN apex_application.e_stop_apex_engine THEN
NULL;
WHEN OTHERS THEN
RAISE;
END;
END;

Someone provided a solution for me in the Oracle forum. I'm not sure why this works and wish I had a better understanding of the error and how this fixes it, but posting here in case others have the same problem.
Oracle Forums Solution

Related

PDF printer generates PDF only when output file name is not set

The following code snippet sends PostScript content (saved in pBuf buffer) to a CutePDF printer:
if (OpenPrinter(printerName, &hPrinter, NULL))
{
DOC_INFO_1 di1;
di1.pDatatype = L"RAW";
di1.pDocName = L"Raw print document";
di1.pOutputFile = NULL;
StartDocPrinter(hPrinter, 1, (LPBYTE)&di1);
StartPagePrinter(hPrinter);
DWORD dwWritten = 0;
WritePrinter(hPrinter, pBuf, dwBufSize, &dwWritten);
EndPagePrinter(hPrinter);
EndDocPrinter(hPrinter);
}
During the execution of this code, a dialog appears where I specify the name of the output file (e.g. D:/out.pdf), after that the pdf file is generated. So far so good. The problems begin when I'm trying to avoid the filename specifying step by changing Line 4 of the snippet:
di1.pOutputFile = L"D:/out.pdf";
Such code doesn't show the dialog during its execution (as expected), but the result D:/out.pdf isn't a pdf file, it's a copy of the PostScript file sent to the printer (copy of the contents of pBuf buffer). PDF Writer behaves in the same way. Why do PDF printers behave in this way and how can I achieve the needed behaviour (generate PDF file without specifying its name in UI)?
The Windows print system behaves this way, because, to be blunt, that's how its supposed to behave. If you specify a filename at that point then the print system sends the output to that file. If you don't specify a filename then it proceeds to normal processing.
Normally you would send the printer driver output to a port, and in the case of PDF printers a custom port monitor would pick up the output (PostScript in this case) and process it further. For PDF printers they send the PostScript on to a process which converts the PostScript to PDF (almost always using Ghostscript, though the Adobe print to PDF tools work the same way).
If you want to alter the output of the PDF process (ie write it to a different file), then you need to alter the way the port monitor works, not the way the print subsystem works, which is what your code is currently doing. By setting a filename where you are, you are simply short-circuiting the process, never invoking the port monitor, which is why the 'save file' dialog does not appear, and why the output is PostScript.
There may be a way of specifying the output file documented for the specific PDF printer you are using. If not, then for open source products (and if GS is built in they should be GPL licensed) you can request a copy of the source code for the product and alter it to suit yourself.
Alternatively, you can pick up a copy of Ghostscript and RedMon (open source Port Monitor) and create your own tool for doing the same job.

Mini-Filter intercept drag & drop file(s) to disk?

I am developing a mini-filter to intercept files and get the name of files which are dragged & dropped to a specific disk and get the file names.
If I drag & drop a file, I can get this file name and intercept it successfully (That's mean this file is not created on disk).
If I drag & drop multiple files, I can only get the first file name and other is not. But when I open the disk, I don't see any file here (That's mean Mini-Filter intercept them successfully). So I can not get the file names (except the first file)
I intercept drag & drop by redirect them:
Get file name by FltGetFileNameInformation() then FltParseFileNameInformation()
Split it two part
First is: \Device\HarddiskVolume1\folder\
Second is: file.ext
Append a file name for first part: \Device\HarddiskVolume1\folder\new_file.ext
Intercept create on disk
Release this buffer: Data->Iopb->TargetFileObject->FileName.Buffer
Assign first part to Data->Iopb->TargetFileObject->FileName
Set this: Data->Iopb->TargetFileObject->RelatedFileObject = NULL;
Data->IoStatus.Information = IO_REPARSE;
Data->IoStatus.Status = STATUS_REPARSE;
return FLT_PREOP_SUCCESS_NO_CALLBACK;
Above code can only intercept all files and get the first file name.
How can I do to intercept each file when I drag & drop multiple file?
I found myself that:
Get file name from Data->Iopb->TargetFileObject->FileName
Slipt it two part: file path and file name
Change file name to a redirect file name
Delete redirect file name. This step can be run before step #1
If redirect file name is not exist, It return STATUS_OBJECT_NAME_NOT_FOUND (0xC0000034). It is not problem for system.
If redirect file name is exist. It is OK.
Make sure you check the simrep sample from Microsoft they show you how to properly do this.
I would not base my assumption that Drag&Drop has a correspondence in the kernel and in the file-system. It can be implemented in user-mode in many ways especially if you are doing it on the same volume. It can be as simple as a rename. Also keep in mind hard-links and symboliclinks and alternate data streams.
Good luck.

Using Firefox website information in C++ program

I am trying to extract information from "about:plugins" website when you use Firefox web browser. I want to be able to use the contents of the website in my C++ program. Only way I know how to use content from another location is reading from a file.
What I am trying to do is read the file name and file path for each plugin from about:plugin'
Not sure if I could send this information to a file and then read it from there, but that seems like double work since if it output to file, I could just read it from there.
Needed to know how to extract information from the Firefox website in order to be used in a C++ program.
Just parse the pluginreg.dat file, you can find it in:
C:\Users\xxxxxxx\AppData\Roaming\Mozilla\Firefox\Profiles\xxxxxx.default
To obtain the AppData
char cAppData[MAX_PATH];
if(SHGetSpecialFolderPathA(NULL, cAppData, CSIDL_APPDATA, false))
{
// To obtain the profile name, parse the profiles.ini file in the folder
// ...AppData\Roaming\Mozilla\Firefox
// ...
}

determine file type c

I am trying to write a client/server program in C++ with Visual Studio 2008. So far the project runs does the following:
Run the webserver on cmd prompt - webserver 8080
open web browser - localhost 8080
to open local html file - localhost:8080/demo.html
But now... let's say the client requests for a gif file, then the server should send gif file.
client request for txt file, then the server should send .txt file. Similarly for .html and .xbm files.
I don't know how to do it.. Any help greatly appreciated.
On UNIX systems you'd use the file command: it uses a set of known "magic number" which are used to identify different file types. anda few heuristics to address the remaining files. Most file formats have some sort of identifier embedded, often in the first couple of bytes. Especially text files normally don't have a magic number but use only printable characters instead (with UTF8 and UTF16 being popular, classifying text files became a bit harder).
Once the file type is determined, you'd just set ghe corresponding HTTP header(s).
okay, because we're in the same class, I'll give you a clue :)
In the header part, put some if-else like this:
if(strcmp(type,"html")==0){
(void) sprintf(buff,"Content-Type:text/html\r\n");
(void) send(conn,buff,strlen(buff),0);
}
else if(strcmp(type,"gif")==0){
(void) sprintf(buff,"Content-Type:image/gif\r\n");
(void) send(conn,buff,strlen(buff),0);
}
Got it? And by the way, you need to get the extension (check path using endsWith function), compare the extension with file type then give out the right header. Test it with gif file :) I have it works already :) Going to submit now. Remember to vote up for me :)

Can thttpd support multipart/form-data?

I could successfully setup thttpd and tested a sample page with form. If I replace the input element with type "file" and post a file upload, thttpd closes the connection without any response but the same works if the input type is text.
So does thttpd supports file uploading ie handling of multipart/form-data? If yes how to handle the same using a cgi written in C/C++?