Use object name as the file name when downloading the template or ISO or volumes
diff --git a/engine/api/src/main/java/org/apache/cloudstack/engine/subsystem/api/storage/DataObject.java b/engine/api/src/main/java/org/apache/cloudstack/engine/subsystem/api/storage/DataObject.java
index 091c09d..fe052f0 100644
--- a/engine/api/src/main/java/org/apache/cloudstack/engine/subsystem/api/storage/DataObject.java
+++ b/engine/api/src/main/java/org/apache/cloudstack/engine/subsystem/api/storage/DataObject.java
@@ -50,4 +50,6 @@
     void decRefCount();
 
     Long getRefCount();
+
+    String getName();
 }
diff --git a/plugins/storage/image/default/src/main/java/org/apache/cloudstack/storage/datastore/driver/CloudStackImageStoreDriverImpl.java b/plugins/storage/image/default/src/main/java/org/apache/cloudstack/storage/datastore/driver/CloudStackImageStoreDriverImpl.java
index 71fa2e9..d2961f0 100644
--- a/plugins/storage/image/default/src/main/java/org/apache/cloudstack/storage/datastore/driver/CloudStackImageStoreDriverImpl.java
+++ b/plugins/storage/image/default/src/main/java/org/apache/cloudstack/storage/datastore/driver/CloudStackImageStoreDriverImpl.java
@@ -25,6 +25,7 @@
 import com.cloud.agent.api.storage.DeleteEntityDownloadURLCommand;
 import com.cloud.host.dao.HostDao;
 import com.cloud.storage.Upload;
+import com.cloud.utils.StringUtils;
 import org.apache.log4j.Logger;
 
 import org.apache.cloudstack.engine.subsystem.api.storage.DataObject;
@@ -64,20 +65,42 @@
         return nfsTO;
     }
 
+    private String createObjectNameForExtractUrl(String installPath, ImageFormat format, DataObject dataObject) {
+        String objectNameInUrl = dataObject.getName();
+        try {
+            objectNameInUrl = cleanObjectName(objectNameInUrl);
+        } catch (Exception e) {
+            objectNameInUrl = UUID.randomUUID().toString();
+        }
+
+        if (format != null) {
+            objectNameInUrl = objectNameInUrl + "." + format.getFileExtension();
+        } else if (installPath.lastIndexOf(".") != -1) {
+            objectNameInUrl = objectNameInUrl + "." + installPath.substring(installPath.lastIndexOf(".") + 1);
+        }
+
+        return objectNameInUrl;
+    }
+
+    private String cleanObjectName(String objectName) {
+        if (StringUtils.isEmpty(objectName)) {
+            throw new IllegalArgumentException("Object name is empty or null");
+        }
+        return objectName.trim()
+                .replaceAll("[^a-zA-Z0-9]+", "-")
+                .replaceAll("-{2,}", "-")
+                .replaceAll("^-|-$", "");
+    }
+
     @Override
     public String createEntityExtractUrl(DataStore store, String installPath, ImageFormat format, DataObject dataObject) {
         // find an endpoint to send command
         EndPoint ep = _epSelector.select(store);
         // Create Symlink at ssvm
         String path = installPath;
-        String uuid = UUID.randomUUID().toString();
-        if (format != null) {
-            uuid = uuid + "." + format.getFileExtension();
-        } else if (path.lastIndexOf(".") != -1) {
-            uuid = uuid + "." + path.substring(path.lastIndexOf(".") + 1);
-        }
+        String objectNameInUrl = createObjectNameForExtractUrl(path, format, dataObject);
         CreateEntityDownloadURLCommand cmd = new CreateEntityDownloadURLCommand(((ImageStoreEntity)store).getMountPoint(),
-                                                                path, uuid, dataObject == null ? null: dataObject.getTO());
+                                                                path, objectNameInUrl, dataObject == null ? null: dataObject.getTO());
         Answer ans = null;
         if (ep == null) {
             String errMsg = "No remote endpoint to send command, check if host or ssvm is down?";
@@ -92,7 +115,7 @@
             throw new CloudRuntimeException(errorString);
         }
         // Construct actual URL locally now that the symlink exists at SSVM
-        return generateCopyUrl(ep.getPublicAddr(), uuid);
+        return generateCopyUrl(ep.getPublicAddr(), objectNameInUrl);
     }
 
     private String generateCopyUrl(String ipAddress, String uuid) {
diff --git a/server/src/main/java/org/apache/cloudstack/diagnostics/to/DiagnosticsDataObject.java b/server/src/main/java/org/apache/cloudstack/diagnostics/to/DiagnosticsDataObject.java
index ebe1d7f..de66ad4 100644
--- a/server/src/main/java/org/apache/cloudstack/diagnostics/to/DiagnosticsDataObject.java
+++ b/server/src/main/java/org/apache/cloudstack/diagnostics/to/DiagnosticsDataObject.java
@@ -99,4 +99,9 @@
     public Long getRefCount() {
         return null;
     }
+
+    @Override
+    public String getName() {
+        return dataStore.getName();
+    }
 }