What is the right way to replace Attachment Data when using Java API?
Asked by Navinesh Prasad:

We want to update the attachment data without creating a new version of the attachment.

The reason for this is that we want to automate ADRMS protection of some documents that are uploaded to confluence.

We have built a REST API plugin that allow an automation solution to upload the NEW (protected) attachment data to confluence.

In the plugin we have tried different methods to make sure confluence understand that the attachment data has been updated.

Here is the current code:

```
@POST
@Path("/replaceAttachmentData")
@Consumes({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML})
@Produces({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML})
public Response replaceAttachmentData(
@QueryParam("AttachmentId") long longAttachmentId,
@QueryParam("Template") String strTemplate,
@QueryParam("LocalPath") String strLocalPath)
{
try {

    Attachment attachment = this.attachmentManager.getAttachmentDao().getById(longAttachmentId);
    if (attachment == null) {
        return Response.ok(new DocCtrlRestResourceModel("Bad AttachmentId")).build();
    }


    File f = new File(strLocalPath);
    if (!f.exists() || f.isDirectory()) {
        return Response.ok(new DocCtrlRestResourceModel("File does not exist")).build();
    }

    long len = f.length();
    InputStream is = new FileInputStream(f);

    attachment.setFileSize(len);

    AttachmentDao attDao = this.attachmentManager.getAttachmentDao();
    attDao.replaceAttachmentData(attachment, is);

    AttachmentDownloadPathCache.AttachmentDownloadPathCacheKey key = this.pathCache.toKey(attachment);
    this.pathCache.remove(key);

    String Filename = attachment.getFileName();
    if (!FilenameUtils.getExtension(strLocalPath).equals(attachment.getFileExtension())) {
        Filename = FilenameUtils.removeExtension(attachment.getFileName()) + "." +
        FilenameUtils.getExtension(strLocalPath);

        log.debug("Renaming attachment to: " + Filename);
    }
    attachment.setFileSize(len);
    
    try {
        attachmentManager.moveAttachment(attachment,
            Filename, attachment.getContainer());
    }
    catch (Exception e) {}

    return Response.ok(new DocCtrlRestResourceModel("Success")).build();
}
catch (Exception e) {
    return Response.ok(new DocCtrlRestResourceModel("Exception: " + e)).build();
}
}
```

With this code we still find document being corrupted. The reason they seem corrupted is that the confluence database keep the wrong size of the attachment data.

When downloading the attachment, confluence sends the number byes stored in the database.  
If the attachment has become bigger, then some of the bytes are missing and the attachment becomes corrupt.

What is the right way of updating the attachment data and to make sure confluence is aware of the update and keep the correct new size in the db?


Answers:
author: Navinesh Prasad
body: This is how we fixed it.  
At least it works for now.

```
@POST
@Path("/replaceAttachmentData")
@Consumes({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML})
@Produces({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML})
public Response replaceAttachmentData(
@QueryParam("AttachmentId") long longAttachmentId,
@QueryParam("Template") String strTemplate,
@QueryParam("LocalPath") String strLocalPath
{
try {

Attachment attachment = this.attachmentManager.getAttachmentDao().getById(longAttachmentId);
if (attachment == null) {
return Response.ok(new DocCtrlRestResourceModel("Bad AttachmentId")).build();
}
File f = new File(strLocalPath);
if (!f.exists() || f.isDirectory()) {
return Response.ok(new DocCtrlRestResourceModel("File does not exist")).build();
}
long len = f.length();
InputStream is = new FileInputStream(f);

AttachmentDao attDao = this.attachmentManager.getAttachmentDao();
attDao.replaceAttachmentData(attachment, is);

attachment.setFileSize(len);

if (!FilenameUtils.getExtension(strLocalPath).equals(attachment.getFileExtension())) {
attachment.setFileName(
FilenameUtils.removeExtension(attachment.getFileName()) + "." +
FilenameUtils.getExtension(strLocalPath));
}

Object res = transactionTemplate.execute(new TransactionCallback()
{
@Override
public Object doInTransaction()
{
attDao.updateAttachment(attachment);
return null;
}
});

return Response.ok(new DocCtrlRestResourceModel("Success")).build();
}
catch (Exception e) {
return Response.ok(new DocCtrlRestResourceModel("Exception: " + e)).build();
}
}
```


Tags: atl-adm

atl-dev

confluence-server

server