[VIVO-1872] - Add download option to SPARQL Query page (#164)

* Add download option to SPARQL Query page

* Set SPARQL query results content type even if downloading

* Address pull request comments
This commit is contained in:
Ben 2020-05-27 22:58:20 -06:00 committed by GitHub
parent 42c69ef04b
commit e198fce908
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 65 additions and 16 deletions

View file

@ -40,6 +40,8 @@ import edu.cornell.mannlib.vitro.webapp.rdfservice.RDFServiceException;
import edu.cornell.mannlib.vitro.webapp.utils.http.AcceptHeaderParsingException; import edu.cornell.mannlib.vitro.webapp.utils.http.AcceptHeaderParsingException;
import edu.cornell.mannlib.vitro.webapp.utils.http.NotAcceptableException; import edu.cornell.mannlib.vitro.webapp.utils.http.NotAcceptableException;
import edu.cornell.mannlib.vitro.webapp.utils.sparql.SparqlQueryUtils; import edu.cornell.mannlib.vitro.webapp.utils.sparql.SparqlQueryUtils;
import edu.cornell.mannlib.vitro.webapp.controller.api.sparqlquery.RdfResultMediaType;
import edu.cornell.mannlib.vitro.webapp.controller.api.sparqlquery.ResultSetMediaType;
/** /**
* Present the SPARQL Query form, and execute the queries. * Present the SPARQL Query form, and execute the queries.
@ -110,11 +112,20 @@ public class SparqlQueryController extends FreemarkerHttpServlet {
.getRDFService(); .getRDFService();
String queryString = req.getParameter("query"); String queryString = req.getParameter("query");
boolean download = Boolean.parseBoolean(req.getParameter("download"));
Query query = SparqlQueryUtils.create(queryString);
try { try {
String format = interpretRequestedFormats(req, queryString); String format = interpretRequestedFormats(req, query);
SparqlQueryApiExecutor core = SparqlQueryApiExecutor.instance( SparqlQueryApiExecutor core = SparqlQueryApiExecutor.instance(
rdfService, queryString, format); rdfService, queryString, format);
resp.setContentType(core.getMediaType()); resp.setContentType(core.getMediaType());
if (download) {
String extension = getFilenameExtension(req, query, format);
resp.setHeader("Content-Transfer-Encoding", "binary");
resp.setHeader("Content-disposition", "attachment; filename=query-results." + extension);
}
core.executeAndFormat(resp.getOutputStream()); core.executeAndFormat(resp.getOutputStream());
} catch (InvalidQueryTypeException e) { } catch (InvalidQueryTypeException e) {
do400BadRequest("Query type is not SELECT, ASK, CONSTRUCT, " do400BadRequest("Query type is not SELECT, ASK, CONSTRUCT, "
@ -132,8 +143,7 @@ public class SparqlQueryController extends FreemarkerHttpServlet {
} }
private String interpretRequestedFormats(HttpServletRequest req, private String interpretRequestedFormats(HttpServletRequest req,
String queryString) throws NotAcceptableException { Query query) throws NotAcceptableException {
Query query = SparqlQueryUtils.create(queryString);
String parameterName = (query.isSelectType() || query.isAskType()) ? "resultFormat" String parameterName = (query.isSelectType() || query.isAskType()) ? "resultFormat"
: "rdfResultFormat"; : "rdfResultFormat";
String parameterValue = req.getParameter(parameterName); String parameterValue = req.getParameter(parameterName);
@ -145,6 +155,20 @@ public class SparqlQueryController extends FreemarkerHttpServlet {
} }
} }
private String getFilenameExtension(HttpServletRequest req,
Query query, String format) {
String extension;
if (query.isSelectType() || query.isAskType()) {
ResultSetMediaType mediaType = ResultSetMediaType.fromContentType(format);
extension = mediaType.getExtension();
}
else {
RdfResultMediaType mediaType = RdfResultMediaType.fromContentType(format);
extension = mediaType.getExtension();
}
return extension;
}
private void do400BadRequest(String message, HttpServletResponse resp) private void do400BadRequest(String message, HttpServletResponse resp)
throws IOException { throws IOException {
resp.setStatus(400); resp.setStatus(400);

View file

@ -12,17 +12,17 @@ import java.util.Map;
* and DESCRIBE). * and DESCRIBE).
*/ */
public enum RdfResultMediaType { public enum RdfResultMediaType {
TEXT("text/plain", true, "NTRIPLE", "N-TRIPLE"), TEXT("text/plain", true, "NTRIPLE", "N-TRIPLE", "nt"),
RDF_XML("application/rdf+xml", true, "RDFXML", "RDF/XML"), RDF_XML("application/rdf+xml", true, "RDFXML", "RDF/XML", "rdf"),
N3("text/n3", true, "N3", "N3"), N3("text/n3", true, "N3", "N3", "n3"),
TTL("text/turtle", false, "N3", "TTL"), TTL("text/turtle", false, "N3", "TTL", "ttl"),
JSON("application/json", false, "N3", "JSON"), JSON("application/json", false, "N3", "JSON", "json"),
JSON_LD("application/ld+json", false, "N3", "JSON"); JSON_LD("application/ld+json", false, "N3", "JSON", "jsonld");
// ---------------------------------------------------------------------- // ----------------------------------------------------------------------
// Keep a map of content types, for easy conversion back and forth // Keep a map of content types, for easy conversion back and forth
@ -79,12 +79,18 @@ public enum RdfResultMediaType {
*/ */
private final String jenaResponseFormat; private final String jenaResponseFormat;
/**
* What extension should be used if file is downloaded?
*/
private final String extension;
private RdfResultMediaType(String contentType, boolean nativeFormat, private RdfResultMediaType(String contentType, boolean nativeFormat,
String serializationFormat, String jenaResponseFormat) { String serializationFormat, String jenaResponseFormat, String extension) {
this.contentType = contentType; this.contentType = contentType;
this.nativeFormat = nativeFormat; this.nativeFormat = nativeFormat;
this.serializationFormat = serializationFormat; this.serializationFormat = serializationFormat;
this.jenaResponseFormat = jenaResponseFormat; this.jenaResponseFormat = jenaResponseFormat;
this.extension = extension;
} }
public String getContentType() { public String getContentType() {
@ -103,4 +109,8 @@ public enum RdfResultMediaType {
return jenaResponseFormat; return jenaResponseFormat;
} }
public String getExtension() {
return extension;
}
} }

View file

@ -12,15 +12,15 @@ import java.util.Map;
* SELECT and ASK). * SELECT and ASK).
*/ */
public enum ResultSetMediaType { public enum ResultSetMediaType {
TEXT("text/plain", true, "TEXT", null), TEXT("text/plain", true, "TEXT", null, "txt"),
CSV("text/csv", true, "CSV", null), CSV("text/csv", true, "CSV", null, "csv"),
TSV("text/tab-separated-values", false, "CSV", "tsv"), TSV("text/tab-separated-values", false, "CSV", "tsv", "tsv"),
XML("application/sparql-results+xml", true, "XML", null), XML("application/sparql-results+xml", true, "XML", null, "xml"),
JSON("application/sparql-results+json", true, "JSON", null); JSON("application/sparql-results+json", true, "JSON", null, "json");
// ---------------------------------------------------------------------- // ----------------------------------------------------------------------
// Keep a map of content types, for easy conversion back and forth // Keep a map of content types, for easy conversion back and forth
@ -78,12 +78,18 @@ public enum ResultSetMediaType {
*/ */
private final String jenaResponseFormat; private final String jenaResponseFormat;
/**
* What extension should be used if file is downloaded?
*/
private final String extension;
private ResultSetMediaType(String contentType, boolean nativeFormat, private ResultSetMediaType(String contentType, boolean nativeFormat,
String rdfServiceFormat, String jenaResponseFormat) { String rdfServiceFormat, String jenaResponseFormat, String extension) {
this.contentType = contentType; this.contentType = contentType;
this.nativeFormat = nativeFormat; this.nativeFormat = nativeFormat;
this.rdfServiceFormat = rdfServiceFormat; this.rdfServiceFormat = rdfServiceFormat;
this.jenaResponseFormat = jenaResponseFormat; this.jenaResponseFormat = jenaResponseFormat;
this.extension = extension;
} }
public String getContentType() { public String getContentType() {
@ -102,4 +108,8 @@ public enum ResultSetMediaType {
return jenaResponseFormat; return jenaResponseFormat;
} }
public String getExtension() {
return extension;
}
} }

View file

@ -27,6 +27,11 @@
<label><input type='radio' name='rdfResultFormat' value='application/json'>JSON-LD</label> <label><input type='radio' name='rdfResultFormat' value='application/json'>JSON-LD</label>
</div> </div>
<div class="options">
<input type="checkbox" id="download" name="download" value="true">
<label for="download"> Save results to file</label><br>
</div>
<input class="submit" type="submit" value="Run Query" /> <input class="submit" type="submit" value="Run Query" />
</form> </form>
</div><!-- content --> </div><!-- content -->