diff --git a/src/main/java/it/inaf/oats/vospace/FileServiceClient.java b/src/main/java/it/inaf/oats/vospace/FileServiceClient.java
index 89d6912f26df618b4b97dcb1049d0fd0adcc6804..d593893059e022ae67e8c2e639ee97ef4ffcb9f4 100644
--- a/src/main/java/it/inaf/oats/vospace/FileServiceClient.java
+++ b/src/main/java/it/inaf/oats/vospace/FileServiceClient.java
@@ -28,7 +28,6 @@ import org.springframework.http.HttpMethod;
 import org.springframework.http.MediaType;
 import org.springframework.stereotype.Component;
 import org.springframework.web.client.RestTemplate;
-import static org.springframework.web.servlet.mvc.method.RequestMappingInfo.paths;
 
 @Component
 public class FileServiceClient {
diff --git a/src/main/java/it/inaf/oats/vospace/UriService.java b/src/main/java/it/inaf/oats/vospace/UriService.java
index aacc7fa2c8bc477b7c50b7cfd3a8fab2797b9081..03162bbc8fcdd0742252cc203c8bba32524acb03 100644
--- a/src/main/java/it/inaf/oats/vospace/UriService.java
+++ b/src/main/java/it/inaf/oats/vospace/UriService.java
@@ -26,6 +26,7 @@ import it.inaf.oats.vospace.persistence.model.Location;
 import it.inaf.oats.vospace.persistence.model.LocationType;
 import java.net.MalformedURLException;
 import java.net.URL;
+import java.nio.charset.StandardCharsets;
 import java.util.ArrayList;
 import java.util.List;
 import java.util.Objects;
@@ -41,6 +42,7 @@ import net.ivoa.xml.vospace.v2.Transfer;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.beans.factory.annotation.Value;
 import org.springframework.stereotype.Service;
+import org.springframework.util.StringUtils;
 
 @Service
 public class UriService {
@@ -179,7 +181,8 @@ public class UriService {
 
     private String getEndpoint(JobSummary job, Transfer transfer) {
 
-        String relativePath = URIUtils.returnVosPathFromNodeURI(transfer.getTarget(), authority);
+        String relativePath = StringUtils.uriDecode(URIUtils
+                .returnVosPathFromNodeURI(transfer.getTarget(), authority), StandardCharsets.UTF_8);
 
         User user = (User) servletRequest.getUserPrincipal();
         String creator = user.getName();
@@ -201,6 +204,7 @@ public class UriService {
             case pullFromVoSpace:
                 // Refresh relative path: it can differ in case of links followed 
                 relativePath = NodeUtils.getVosPath(node);
+                relativePath = StringUtils.uriDecode(relativePath, StandardCharsets.UTF_8);
                 if (!NodeUtils.checkIfReadable(node, creator, groups)) {
                     throw PermissionDeniedException.forPath(relativePath);
                 }
diff --git a/src/test/java/it/inaf/oats/vospace/UriServiceTest.java b/src/test/java/it/inaf/oats/vospace/UriServiceTest.java
index 3b98d4fa219678f64c6cff19d9e9cf8527396c5b..a62f19ea3110dd1dc4286a9e147335cbe3e4b1ba 100644
--- a/src/test/java/it/inaf/oats/vospace/UriServiceTest.java
+++ b/src/test/java/it/inaf/oats/vospace/UriServiceTest.java
@@ -560,6 +560,38 @@ public class UriServiceTest {
         assertTrue(ex.getMessage().contains("no protocol"));
     }
 
+    @Test
+    public void testPullFileWithSpecialChars() {
+
+        DataNode node = new DataNode();
+        node.setUri("vos://example.com!vospace/(%20+%20).txt");
+
+        Property publicProperty = new Property();
+        publicProperty.setUri(NodeProperties.PUBLIC_READ_URI);
+        publicProperty.setValue(String.valueOf(true));
+        node.getProperties().add(publicProperty);
+
+        when(nodeDAO.listNode(eq("/( + ).txt"))).thenReturn(Optional.of(node));
+
+        Transfer transfer = new Transfer();
+        transfer.setDirection("pullFromVoSpace");
+        transfer.setTarget("vos://example.com!vospace/(%20+%20).txt");
+
+        Protocol protocol = new Protocol();
+        protocol.setUri("ivo://ivoa.net/vospace/core#httpget");
+        transfer.getProtocols().add(protocol);
+
+        JobSummary job = new JobSummary();
+        JobSummary.JobInfo jobInfo = new JobSummary.JobInfo();
+        jobInfo.getAny().add(transfer);
+        job.setJobInfo(jobInfo);
+
+        Transfer negotiatedTransfer = uriService.getNegotiatedTransfer(job, transfer);
+
+        assertEquals(1, negotiatedTransfer.getProtocols().size());
+        assertTrue(negotiatedTransfer.getProtocols().get(0).getEndpoint().contains("/%28%20%2B%20%29.txt"));
+    }
+
     private void testArchiveViewEndpoint(String viewUri) {
 
         Transfer transfer = new Transfer();