Overview
Examples
Screenshots
Comparisons
Applications
Download
Documentation
Tutorials
Bazaar
Status & Roadmap
FAQ
Authors & License
Forums
Funding Ultimate++
Search on this site
Search in forums












SourceForge.net Logo
Home » U++ Library support » Skylark » Proposition: Adding a way to send huge file via stream in skylark
Proposition: Adding a way to send huge file via stream in skylark [message #57568] Sun, 26 September 2021 22:18
Xemuth is currently offline  Xemuth
Messages: 387
Registered: August 2018
Location: France
Senior Member
While testing my skylark application on a raspberry I noticed that trying to read huge file ( upper to 1Go) make the crash app. Indeed the way I did it was the following :
http.SetHeader("content-disposition", "attachment; filename=\"" + f->FileName +"\"").ContentType("application/octet-stream") <<  LoadFile(f->FilePath);

Loading a huge file into memory in order to send it in one chunk is not a good idea, especially on low memory platform. That's why I worked on adding a way for skylark to send file in chunk :


http.SetHeader("content-disposition", "attachment; filename=\"" + f->FileName +"\"").ContentType("application/octet-stream").SendFile(f->FilePath);


Http.h
class Http : public Renderer {
...
private:
FileIn responseStream;
int chunkSize;
...
}


Http.cpp
Http& Http::SendFile(const Upp::String& filePath, int _chunkSize){
	if(FileExists(filePath)){
		chunkSize = _chunkSize;
		responseStream.Open(filePath);
	}
	return *this;
}



Dispatch.cpp
void Http::Finalize(bool closeSocket)
{
    if(rsocket) {
        SKYLARKLOG("=== Response: " << code << ' ' << code_text);
        String r;

        // weird apache2 mod_scgi behaviour
        if(hdr.scgi)
            r << "Status: ";
        else
            r << "HTTP/1.1 ";

        if(redirect.GetCount()) {
            // for SCGI (at least on apache 2 mod_scgi), we need protocol inside url
            if(hdr.scgi && redirect.Find(":") < 0)
                redirect = "http:" + redirect;

            SKYLARKLOG("Redirect to: " << redirect);
            r << code << " Found\r\n";
            r << "Location: " << redirect << "\r\n";
            for(int i = 0; i < cookies.GetCount(); i++)
                r << cookies[i];
        }
        else {
            r <<
                code << ' ' << code_text << "\r\n"
                "Date: " <<  WwwFormat(GetUtcTime()) << "\r\n";
                if(responseStream){
                    r << "Content-Length: " << responseStream.GetSize() << "\r\n";
                }else{
					r << "Content-Length: " << response.GetCount() << "\r\n";
                }
                r << "Content-Type: " << content_type << "\r\n";
                
            for(int i = 0; i < headers.GetCount(); i++)
                r << headers.GetKey(i) << ": " << headers[i] << "\r\n";
            for(int i = 0; i < cookies.GetCount(); i++)
                r << cookies[i];
        }
        r << "\r\n";
        rsocket->PutAll(r);
        if(responseStream){
            Upp::String fileData = "";
			while((fileData = responseStream.Get(chunkSize)).GetCount() > 0){
				rsocket->PutAll(fileData);
				fileData = "";
			}
			rsocket->PutAll("\r\n");
			responseStream.Close();
        }else{
            rsocket->PutAll(response);
        }
        
        rsocket = NULL;
    }
}


Via this new method huge file can be send over a skylark handler
Previous Topic: Skylark : GetIdentity alternative way of working
Next Topic: delete the file from the skylark/server after download
Goto Forum:
  


Current Time: Fri Mar 29 11:32:58 CET 2024

Total time taken to generate the page: 0.01324 seconds