diff --git a/VERSIONS_HOTLINE/95613 b/VERSIONS_HOTLINE/95613
new file mode 100644
index 0000000000000000000000000000000000000000..a20e2ac377a949f1497e09c24c57e38d3ec02056
--- /dev/null
+++ b/VERSIONS_HOTLINE/95613
@@ -0,0 +1 @@
+ - ticket #95613 : Redmine : accès aux pièces jointes de la forge via Bokeh
\ No newline at end of file
diff --git a/application/modules/admin/controllers/RedmineController.php b/application/modules/admin/controllers/RedmineController.php
index a6dc51e07e5406fc71a4795bb55a0717e2a38597..5f69c41b0800933f077f4c822630ce85b1247f13 100644
--- a/application/modules/admin/controllers/RedmineController.php
+++ b/application/modules/admin/controllers/RedmineController.php
@@ -175,6 +175,21 @@ class Admin_RedmineController extends ZendAfi_Controller_Action {
   }
 
 
+  public function downloadFileAction() {
+    $library = Class_Bib::find($this->_getParam('id_lib', 0));
+    $service = new Class_WebService_Redmine($library);
+    $fileid = $this->_getParam('fileid');
+
+    if (!$content = $service->downloadFile($fileid)) {
+      $this->_helper->notify($this->_('Impossible de télécharger cette pièce jointe'));
+      $this->_redirectToReferer();
+      return;
+    }
+
+    $this->_helper->binaryDownload($content, $this->_getParam('filename'));
+  }
+
+
   public function uploadFileAction() {
     if (!$this->_request->isPost())
       return $this->_jsonError($this->_('La requête doit être de type POST'));
diff --git a/library/Class/WebService/Redmine.php b/library/Class/WebService/Redmine.php
index 89c41bab2b3117bea6b1facaf465967e778b1087..3ae9be3ffa6f2966dcbbb0ad1da739471aefe67a 100644
--- a/library/Class/WebService/Redmine.php
+++ b/library/Class/WebService/Redmine.php
@@ -20,7 +20,7 @@
  */
 
 class Class_WebService_Redmine extends Class_WebService_Abstract {
-   use Trait_Translator;
+  use Trait_Translator;
 
    const CUSTOM_PRIORITY_ID = 5;
    const CUSTOM_MODULE_ID = 37;
@@ -381,8 +381,12 @@ class Class_WebService_Redmine extends Class_WebService_Abstract {
 
 
   public function uploadFile($json) {
-    return $this->_getAttachmentApi()
-                ->upload($json);
+    return $this->_getAttachmentApi()->upload($json);
+  }
+
+
+  public function downloadFile($fileid) {
+    return $this->_getAttachmentApi()->download($fileid);
   }
 
 
diff --git a/library/Class/WebService/Redmine/Issue.php b/library/Class/WebService/Redmine/Issue.php
index e3bccad28f6e0c8973cab5ad2ee50175a60d4622..bfb49055070fe2fed501b7b57d3cf35c40f63e1f 100644
--- a/library/Class/WebService/Redmine/Issue.php
+++ b/library/Class/WebService/Redmine/Issue.php
@@ -139,10 +139,12 @@ class Class_WebService_Redmine_Issue extends Class_Entity {
       return $view->tag('del',
                         $this->_('Pièce jointe : "%s"', $attachment->getold_value()));
 
-    $show_url = sprintf('%s/attachments/download/%s/%s',
-                   Class_AdminVar::get('REDMINE_SERVER_URL'),
-                   $attachment->getname(),
-                   $attachment->getnew_value());
+    $show_url = Class_Url::absolute(['module' => 'admin',
+                                     'controller' => 'redmine',
+                                     'action' => 'download-file',
+                                     'id_lib' => $this->getLibrary()->getId(),
+                                     'fileid' => $attachment->getname(),
+                                     'filename' => $attachment->getnew_value()],null,true);
 
     return $view->tagAnchor($show_url,
                             $this->_('Pièce jointe : "%s"', $attachment->getnew_value()), ['target' => '_blank']);
diff --git a/tests/application/modules/admin/controllers/RedmineControllerTest.php b/tests/application/modules/admin/controllers/RedmineControllerTest.php
index 3b84848c1d754d888c1d66658c3e6a7fecc1e992..a94fef7ab9b30f8dcc8630b702034325bcc693f8 100644
--- a/tests/application/modules/admin/controllers/RedmineControllerTest.php
+++ b/tests/application/modules/admin/controllers/RedmineControllerTest.php
@@ -52,6 +52,7 @@ abstract class Admin_RedmineControllerTestCase extends Admin_AbstractControllerT
 
 
 
+
 class Admin_RedmineControllerTestActionWithNoBibTest extends Admin_RedmineControllerTestCase {
   public function setUp() {
     parent::setUp();
@@ -67,6 +68,7 @@ class Admin_RedmineControllerTestActionWithNoBibTest extends Admin_RedmineContro
 
 
 
+
 abstract class Admin_RedmineControllerWithAnnecyLibraryTestCase extends Admin_RedmineControllerTestCase {
 
   public function setUp() {
@@ -560,6 +562,13 @@ class Admin_RedmineControllerEditIssue34247Test extends Admin_RedmineControllerF
   public function historyShouldBePresent() {
     $this->assertXPathContentContains('//legend', 'Historique');
   }
+
+
+  /** @test */
+  public function attachmentShouldLinkToDownloadFile() {
+    $this->assertXPathContentContains('//a[contains(@href,"download-file/id_lib/1/fileid/456789/filename/proof.jpg")]', 'proof.jpg', $this->_response->getBody());
+  }
+
 }
 
 
@@ -863,3 +872,74 @@ class Admin_RedmineControllerPostEditIssue34247WithAttachmentTest extends Admin_
     $this->assertRedirect();
   }
 }
+
+
+
+class Admin_RedmineControllerTestActionDownloadAttachmentTest
+  extends Admin_RedmineControllerWithAnnecyLibraryTestCase {
+
+  public function setUp() {
+    parent::setUp();
+
+    $redmine_api = $this->mock()
+                        ->whenCalled('download')
+                        ->with(123)
+                        ->answers('toto');
+
+    $redmine_client = $this->mock()
+                           ->whenCalled('api')
+                           ->answers($redmine_api);
+
+    Class_WebService_Redmine::setClient($redmine_client);
+
+    $this->dispatch('/admin/redmine/download-file/id_lib/1/fileid/123/filename/test.txt', true);
+  }
+
+
+  /** @test */
+  public function responseBodyShouldBeToto() {
+    $this->assertEquals('toto', $this->_response->getBody());
+  }
+
+
+  /** @test */
+  public function contentTypeShouldBeApplicationOctetStream() {
+    $this->assertEquals('application/octet-stream; name="test.txt"',
+                        $this->_response->getHeaders()[0]['value']);
+  }
+}
+
+
+
+class Admin_RedmineControllerTestActionDownloadEmptyAttachmentTest
+  extends Admin_RedmineControllerWithAnnecyLibraryTestCase {
+
+  public function setUp() {
+    parent::setUp();
+
+    $redmine_api = $this->mock()
+                        ->whenCalled('download')
+                        ->with(123)
+                        ->answers('');
+
+    $redmine_client = $this->mock()
+                           ->whenCalled('api')
+                           ->answers($redmine_api);
+
+    Class_WebService_Redmine::setClient($redmine_client);
+
+    $this->dispatch('/admin/redmine/download-file/id_lib/1/fileid/123/filename/test.txt', true);
+  }
+
+
+  /** @test */
+  public function shouldNotifyError() {
+    $this->assertFlashMessengerContentContains('Impossible de télécharger cette pièce jointe');
+  }
+
+
+  /** @test */
+  public function shouldRedirect() {
+    $this->assertRedirect();
+  }
+}
\ No newline at end of file