Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Server: FILE_NAME parameter to set Content-Disposition header from cl…
…ient
  • Loading branch information
mhugent committed Jul 7, 2015
1 parent 4f212d3 commit 46c0568
Show file tree
Hide file tree
Showing 4 changed files with 60 additions and 44 deletions.
47 changes: 26 additions & 21 deletions src/server/qgshttprequesthandler.cpp
Expand Up @@ -72,6 +72,24 @@ bool QgsHttpRequestHandler::exceptionRaised() const
return mException != NULL;
}

void QgsHttpRequestHandler::setDefaultHeaders()
{
//format
QString format = mInfoFormat;
if ( mInfoFormat.startsWith( "text/" ) )
{
format.append( "; charset=utf-8" );
}
setHeader( "Content-Type", format );

//length
int contentLength = mBody.size();
if ( contentLength > 0 ) // size is not known when streaming
{
setHeader( "Content-Length", QString::number( contentLength ) );
}
}

void QgsHttpRequestHandler::setHeader( const QString &name, const QString &value )
{
mHeaders.insert( name, value );
Expand Down Expand Up @@ -133,29 +151,16 @@ void QgsHttpRequestHandler::sendHeaders()
// Send default headers if they've not been set in a previous stage
if ( mHeaders.empty() )
{
QgsDebugMsg( QString( "Content size: %1" ).arg( mBody.size() ) );
QgsDebugMsg( QString( "Content format: %1" ).arg( mInfoFormat ) );
addToResponseHeader( "Content-Type: " );
addToResponseHeader( mInfoFormat.toUtf8() );
if ( mInfoFormat.startsWith( "text/" ) )
addToResponseHeader( "; charset=utf-8" );
addToResponseHeader( "\n" );
// size is not known when streaming
if ( mBody.size() > 0 )
{
addToResponseHeader( QString( "Content-Length: %1\n" ).arg( mBody.size() ).toUtf8( ) );
}
setDefaultHeaders();
}
else

QMap<QString, QString>::const_iterator it;
for ( it = mHeaders.constBegin(); it != mHeaders.constEnd(); ++it )
{
QMap<QString, QString>::const_iterator it;
for ( it = mHeaders.constBegin(); it != mHeaders.constEnd(); ++it )
{
addToResponseHeader( it.key().toUtf8() );
addToResponseHeader( ": " );
addToResponseHeader( it.value().toUtf8() );
addToResponseHeader( "\n" );
}
addToResponseHeader( it.key().toUtf8() );
addToResponseHeader( ": " );
addToResponseHeader( it.value().toUtf8() );
addToResponseHeader( "\n" );
}
addToResponseHeader( "\n" );
mHeaders.clear();
Expand Down
1 change: 1 addition & 0 deletions src/server/qgshttprequesthandler.h
Expand Up @@ -48,6 +48,7 @@ class QgsHttpRequestHandler: public QgsRequestHandler
virtual void setGetCoverageResponse( QByteArray* ba ) override;
/** Send out HTTP headers and flush output buffer*/
virtual void sendResponse() override;
virtual void setDefaultHeaders() override;
virtual void setHeader( const QString &name, const QString &value ) override;
virtual int removeHeader( const QString &name ) override;
virtual void clearHeaders( ) override;
Expand Down
47 changes: 24 additions & 23 deletions src/server/qgsrequesthandler.h
Expand Up @@ -37,7 +37,7 @@ class QDomDocument;
class QImage;
class QgsMapServiceException;

/**This class is an interface hiding the details of reading input and writing output from/to a wms request mechanism.
/** This class is an interface hiding the details of reading input and writing output from/to a wms request mechanism.
Examples of possible mechanisms are cgi Get, cgi Post, SOAP or the usage as a standalone command line executable*/
class QgsRequestHandler
{
Expand All @@ -49,13 +49,13 @@ class QgsRequestHandler
, mException( 0 )
{}
virtual ~QgsRequestHandler( ) {}
/**Parses the input and creates a request neutral Parameter/Value map*/
/** Parses the input and creates a request neutral Parameter/Value map*/
virtual void parseInput() = 0;
/**Sends the map image back to the client*/
/** Sends the map image back to the client*/
virtual void setGetMapResponse( const QString& service, QImage* img, int imageQuality ) = 0;
virtual void setGetCapabilitiesResponse( const QDomDocument& doc ) = 0;
virtual void setGetFeatureInfoResponse( const QDomDocument& infoDoc, const QString& infoFormat ) = 0;
/**Allow plugins to return a QgsMapServiceException*/
/** Allow plugins to return a QgsMapServiceException*/
virtual void setServiceException( QgsMapServiceException ex ) = 0;
virtual void setXmlResponse( const QDomDocument& doc ) = 0;
virtual void setXmlResponse( const QDomDocument& doc, const QString& mimeType ) = 0;
Expand All @@ -64,45 +64,46 @@ class QgsRequestHandler
virtual void setGetFeatureResponse( QByteArray* ba ) = 0;
virtual void endGetFeatureResponse( QByteArray* ba ) = 0;
virtual void setGetCoverageResponse( QByteArray* ba ) = 0;
/**Set an HTTP header*/
virtual void setDefaultHeaders() {}
/** Set an HTTP header*/
virtual void setHeader( const QString &name, const QString &value ) = 0;
/**Remove an HTTP header*/
/** Remove an HTTP header*/
virtual int removeHeader( const QString &name ) = 0;
/**Delete all HTTP headers*/
/** Delete all HTTP headers*/
virtual void clearHeaders( ) = 0;
/**Append the bytestream to response body*/
/** Append the bytestream to response body*/
virtual void appendBody( const QByteArray &body ) = 0;
/**Clears the response body*/
/** Clears the response body*/
virtual void clearBody( ) = 0;
/**Return the response body*/
/** Return the response body*/
virtual QByteArray body() { return mBody; }
/**Set the info format string such as "text/xml"*/
/** Set the info format string such as "text/xml"*/
virtual void setInfoFormat( const QString &format ) = 0;
/**Check whether there is any header set or the body is not empty*/
/** Check whether there is any header set or the body is not empty*/
virtual bool responseReady() const = 0;
/**Send out HTTP headers and flush output buffer*/
/** Send out HTTP headers and flush output buffer*/
virtual void sendResponse( ) = 0;
/**Pointer to last raised exception*/
/** Pointer to last raised exception*/
virtual bool exceptionRaised() const = 0;
/**Return a copy of the parsed parameters as a key-value pair, to modify
/** Return a copy of the parsed parameters as a key-value pair, to modify
* a parameter setParameter( const QString &key, const QString &value)
* and removeParameter(const QString &key) must be used
*/
QMap<QString, QString> parameterMap() { return mParameterMap; }
/**Set a request parameter*/
/** Set a request parameter*/
virtual void setParameter( const QString &key, const QString &value ) = 0;
/**Remove a request parameter*/
/** Remove a request parameter*/
virtual int removeParameter( const QString &key ) = 0;
/**Return a request parameter*/
/** Return a request parameter*/
virtual QString parameter( const QString &key ) const = 0;
/**Return the requested format string*/
/** Return the requested format string*/
QString format() const { return mFormat; }
/**Return the mime type for the response*/
/** Return the mime type for the response*/
QString infoFormat() const { return mInfoFormat; }
/**Return true if the HTTP headers were already sent to the client*/
/** Return true if the HTTP headers were already sent to the client*/
bool headersSent() { return mHeadersSent; }
#ifdef HAVE_SERVER_PYTHON_PLUGINS
/**Allow core services to call plugin hooks through sendResponse() */
/** Allow core services to call plugin hooks through sendResponse() */
virtual void setPluginFilters( QgsServerFiltersMap pluginFilters ) = 0;
#endif
// TODO: if HAVE_SERVER_PYTHON
Expand All @@ -118,7 +119,7 @@ class QgsRequestHandler
QgsServerFiltersMap mPluginFilters;
#endif
QByteArray mBody; // The response payload
/**This is set by the parseInput methods of the subclasses (parameter FORMAT, e.g. 'FORMAT=PNG')*/
/** This is set by the parseInput methods of the subclasses (parameter FORMAT, e.g. 'FORMAT=PNG')*/
QString mFormat;
QString mFormatString; //format string as it is passed in the request (with base)
bool mHeadersSent;
Expand Down
9 changes: 9 additions & 0 deletions src/server/qgsserver.cpp
Expand Up @@ -583,6 +583,15 @@ QByteArray QgsServer::handleRequest( const QString queryString ,
filtersIterator.value()->responseComplete();
}
#endif

//possibility for client to suggest a download filename
QString outputFileName = theRequestHandler->parameter( "FILE_NAME" );
if ( !outputFileName.isEmpty() )
{
theRequestHandler->setDefaultHeaders();
theRequestHandler->setHeader( "Content-Disposition", "attachment; filename=\"" + outputFileName + "\"" );
}

theRequestHandler->sendResponse();

if ( logLevel < 1 )
Expand Down

0 comments on commit 46c0568

Please sign in to comment.