diff --git a/workhorse/internal/artifacts/entry.go b/workhorse/internal/artifacts/entry.go
index e727e82ec5f5735306c7c935209b49297d022476..0c697d400204d0a9015ee1e9c850811e7a3fddab 100644
--- a/workhorse/internal/artifacts/entry.go
+++ b/workhorse/internal/artifacts/entry.go
@@ -5,6 +5,7 @@ import (
 	"context"
 	"fmt"
 	"io"
+	"mime"
 	"net/http"
 	"os"
 	"os/exec"
@@ -52,6 +53,14 @@ func (e *entry) Inject(w http.ResponseWriter, r *http.Request, sendData string)
 	}
 }
 
+func detectFileContentType(fileName string) string {
+	contentType := mime.TypeByExtension(filepath.Ext(fileName))
+	if contentType == "" {
+		contentType = "application/octet-stream"
+	}
+	return contentType
+}
+
 func unpackFileFromZip(ctx context.Context, archivePath, encodedFilename string, headers http.Header, output io.Writer) error {
 	fileName, err := zipartifacts.DecodeFileEntry(encodedFilename)
 	if err != nil {
@@ -88,15 +97,7 @@ func unpackFileFromZip(ctx context.Context, archivePath, encodedFilename string,
 
 	// Write http headers about the file
 	headers.Set("Content-Length", contentLength)
-
-	// Using application/octet-stream tells the client that we don't
-	// really know what Content-Type is. Since this file is being sent
-	// as attachment, browsers don't need to know to save the
-	// file. Chrome doesn't appear to pay attention to Content-Type when
-	// Content-Disposition is an attachment, and Firefox only uses it if there
-	// is no extension in the filename. Thus, there's no need for
-	// Workhorse to guess Content-Type based on the filename.
-	headers.Set("Content-Type", "application/octet-stream")
+	headers.Set("Content-Type", detectFileContentType(fileName))
 	headers.Set("Content-Disposition", "attachment; filename=\""+escapeQuotes(basename)+"\"")
 	// Copy file body to client
 	if _, err := io.Copy(output, reader); err != nil {
diff --git a/workhorse/internal/artifacts/entry_test.go b/workhorse/internal/artifacts/entry_test.go
index 35e2bf06a0c89732e292e6465ca2c48d385a19b0..6f1e9d360aae3cd01d9d941cd85722ff5eafcac5 100644
--- a/workhorse/internal/artifacts/entry_test.go
+++ b/workhorse/internal/artifacts/entry_test.go
@@ -54,7 +54,7 @@ func TestDownloadingFromValidArchive(t *testing.T) {
 
 	testhelper.RequireResponseHeader(t, response,
 		"Content-Type",
-		"application/octet-stream")
+		"text/plain; charset=utf-8")
 	testhelper.RequireResponseHeader(t, response,
 		"Content-Disposition",
 		"attachment; filename=\"test.txt\"")
@@ -88,7 +88,7 @@ func TestDownloadingFromValidHTTPArchive(t *testing.T) {
 
 	testhelper.RequireResponseHeader(t, response,
 		"Content-Type",
-		"application/octet-stream")
+		"text/plain; charset=utf-8")
 	testhelper.RequireResponseHeader(t, response,
 		"Content-Disposition",
 		"attachment; filename=\"test.txt\"")