Skip to content

Commit 21d9e6f

Browse files
Merge pull request #413 from cap-java/attachmentSize
Support Attachment size restriction during upload
2 parents 6313813 + 7ef8b0c commit 21d9e6f

7 files changed

Lines changed: 144 additions & 4 deletions

File tree

.github/workflows/multiTenancyDeployLocal.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -121,4 +121,4 @@ jobs:
121121
ls -lrth
122122
echo "▶️ Running cf deploy..."
123123
cf deploy mta_archives/bookshop-mt_1.0.0.mtar -f
124-
echo "✅ Deployment complete!"
124+
echo "✅ Deployment complete!"

README.md

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ This plugin can be consumed by the CAP application deployed on BTP to store thei
1515
- Display attachments specific to repository: Lists attachments contained in the repository that is configured with the CAP application.
1616
- Custom properties : Provides the capability to define custom properties for attachments.
1717
- Maximum allowed uploads: Provides the capability to define the maximum number of uploads allowed for the user.
18+
- Maximum file size: Provides the capability to specify the maximum file size for attachments.
1819
- Multiple attachment facets: Provides the capability to define multiple attachment facets/sections in the CAP Entity.
1920
- Technical user support: Provides the capability to consume the plugin using technical user.
2021
- Copy attachments: Provides the capability to copy attachments from one entity to another entity.
@@ -34,6 +35,7 @@ This plugin can be consumed by the CAP application deployed on BTP to store thei
3435
- [Support for Multitenancy](#support-for-multitenancy)
3536
- [Support for Custom Properties](#support-for-custom-properties)
3637
- [Support for Maximum allowed uploads](#support-for-maximum-allowed-uploads)
38+
- [Support for Maximum File Size](#support-for-maximum-file-size)
3739
- [Support for Multiple attachment facets](#support-for-multiple-attachment-facets)
3840
- [Support for Technical user](#support-for-technical-user)
3941
- [Support for Copy attachments](#support-for-copy-attachments)
@@ -492,6 +494,35 @@ SDM.maxCountErrorMessage = Maximale Anzahl von Anhängen erreicht
492494
>
493495
> Once the maxCount is configured, it is recommended not to alter it. If the maxCount is altered, the previously uploaded documents will still be visible.
494496
497+
## Support for Maximum File Size
498+
499+
This plugin allows you to customize the maximum file size for attachments that a user can upload. Once the defined file size limit is exceeded, the upload is rejected and an error is triggered. The error message displayed to the user is fully customizable. The `@Validation.Maximum` annotation is used to define the maximum allowed file size.
500+
501+
Refer the following example from a sample Bookshop app:
502+
503+
```cds
504+
505+
entity Books {
506+
...
507+
attachments: Composition of many Attachments;
508+
}
509+
510+
annotate Books.attachments with {
511+
content @Validation.Maximum : '30MB';
512+
}
513+
```
514+
515+
#### Customizing the Maximum File Size Error Message
516+
517+
To customize the error message displayed when the file upload size limit is exceeded, add the following key to your `messages.properties` file under `srv/src/main/resources`:
518+
519+
```properties
520+
AttachmentSizeExceeded = File size exceeds the limit of {0}.
521+
```
522+
523+
Supports both decimal (KB, MB, GB, TB) and binary (KiB, MiB, GiB, TiB) units with comprehensive validation and error handling.
524+
525+
495526
## Support for Multiple attachment facets
496527
The plugin supports creating multiple attachment facets or sections, each allowing various documents to be uploaded. The names of these facets are fully customizable. All existing operations available for the default attachment facet are also supported for any additional facets you create.
497528

@@ -1316,4 +1347,4 @@ We as members, contributors, and leaders pledge to make participation in our com
13161347

13171348
## Licensing
13181349

1319-
Copyright 2024 SAP SE or an SAP affiliate company and <your-project> contributors. Please see our [LICENSE](LICENSE) for copyright and license information. Detailed information including third-party components and their licensing/copyright information is available [via the REUSE tool](https://api.reuse.software/info/github.com/cap-java/sdm).
1350+
Copyright 2024 SAP SE or an SAP affiliate company and <your-project> contributors. Please see our [LICENSE](LICENSE) for copyright and license information. Detailed information including third-party components and their licensing/copyright information is available [via the REUSE tool](https://api.reuse.software/info/github.com/cap-java/sdm).

pom.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@
3737
<test-spring-boot-version>3.2.5</test-spring-boot-version>
3838
<sdk-bom-version>5.21.0</sdk-bom-version>
3939
<mockito-bom-version>5.15.2</mockito-bom-version>
40-
<assertj-core-version>3.27.3</assertj-core-version>
40+
<assertj-core-version>3.27.7</assertj-core-version>
4141
<mockito-core-version>5.15.2</mockito-core-version>
4242
</properties>
4343

sdm/pom.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@
3434
<test-generation-folder>src/test/gen</test-generation-folder>
3535
<maven.compiler.source>17</maven.compiler.source>
3636
<maven.compiler.target>17</maven.compiler.target>
37-
<attachments_version>1.2.4</attachments_version>
37+
<attachments_version>1.3.0</attachments_version>
3838
<lombok.version>1.18.36</lombok.version>
3939
<jacoco.version>0.8.7</jacoco.version>
4040
<ehcache-version>3.10.8</ehcache-version>

sdm/src/test/java/integration/com/sap/cds/sdm/IntegrationTest_MultipleFacet.java

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7210,4 +7210,63 @@ public void testMoveAttachmentsWithoutSDMRole() throws Exception {
72107210
api.deleteEntity(appUrl, entityName, moveSourceEntity);
72117211
}
72127212
}
7213+
7214+
// @Test
7215+
// @Order(76)
7216+
// void testUploadAttachmentExceedingMaximumFileSize() throws IOException {
7217+
// System.out.println(
7218+
// "Test (76) : Upload attachment exceeding maximum file size in references facet");
7219+
7220+
// // Create a new entity
7221+
// String response = api.createEntityDraft(appUrl, entityName, entityName2, srvpath);
7222+
// if (response.equals("Could not create entity")) {
7223+
// fail("Could not create entity");
7224+
// }
7225+
// String testEntityID = response;
7226+
7227+
// // Load the 150MB sample file
7228+
// ClassLoader classLoader = getClass().getClassLoader();
7229+
// File file = new File(classLoader.getResource("sample32mb.pdf").getFile());
7230+
7231+
// for (int i = 0; i < facet.length; i++) {
7232+
// Map<String, Object> postData = new HashMap<>();
7233+
// postData.put("up__ID", testEntityID);
7234+
// postData.put("mimeType", "application/pdf");
7235+
// postData.put("createdAt", new Date().toString());
7236+
// postData.put("createdBy", "test@test.com");
7237+
// postData.put("modifiedBy", "test@test.com");
7238+
7239+
// List<String> createResponse =
7240+
// api.createAttachment(appUrl, entityName, facet[i], testEntityID, srvpath, postData,
7241+
// file);
7242+
// String check = createResponse.get(0);
7243+
7244+
// // Only 'references' facet has 30MB limit, others should succeed
7245+
// if (facet[i].equals("references")) {
7246+
// // The upload should fail with AttachmentSizeExceeded error
7247+
// if (!check.equals("Attachment created")) {
7248+
// try {
7249+
// JSONObject json = new JSONObject(check);
7250+
// String errorCode = json.getJSONObject("error").getString("code");
7251+
// String errorMessage = json.getJSONObject("error").getString("message");
7252+
// assertEquals("413", errorCode);
7253+
// assertEquals("File size exceeds the limit of 30MB.", errorMessage);
7254+
// } catch (Exception e) {
7255+
// fail("Failed to parse error response for references facet: " + e.getMessage());
7256+
// }
7257+
// } else {
7258+
// fail("Attachment got created in references facet with file size exceeding maximum
7259+
// limit");
7260+
// }
7261+
// } else {
7262+
// // For attachments and footnotes, expect success
7263+
// if (!check.equals("Attachment created")) {
7264+
// fail("Attachment upload failed in " + facet[i] + " facet: " + check);
7265+
// }
7266+
// }
7267+
// }
7268+
7269+
// // delete the draft entity
7270+
// api.deleteEntityDraft(appUrl, entityName, testEntityID);
7271+
// }
72137272
}

sdm/src/test/java/integration/com/sap/cds/sdm/IntegrationTest_SingleFacet.java

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6650,4 +6650,54 @@ public void testMoveAttachmentsWithoutSDMRole() throws Exception {
66506650
api.deleteEntity(appUrl, entityName, moveTargetEntity);
66516651
api.deleteEntity(appUrl, entityName, moveSourceEntity);
66526652
}
6653+
6654+
// @Test
6655+
// @Order(76)
6656+
// void testUploadAttachmentExceedingMaximumFileSize() throws IOException {
6657+
// System.out.println(
6658+
// "Test (76) : Upload attachment exceeding maximum file size in references facet");
6659+
6660+
// // Create a new entity
6661+
// String response = api.createEntityDraft(appUrl, entityName, entityName2, srvpath);
6662+
// if (response.equals("Could not create entity")) {
6663+
// fail("Could not create entity");
6664+
// }
6665+
// String testEntityID = response;
6666+
6667+
// // Load the 150MB sample file
6668+
// ClassLoader classLoader = getClass().getClassLoader();
6669+
// File file = new File(classLoader.getResource("sample32mb.pdf").getFile());
6670+
6671+
// Map<String, Object> postData = new HashMap<>();
6672+
// postData.put("up__ID", testEntityID);
6673+
// postData.put("mimeType", "application/pdf");
6674+
// postData.put("createdAt", new Date().toString());
6675+
// postData.put("createdBy", "test@test.com");
6676+
// postData.put("modifiedBy", "test@test.com");
6677+
6678+
// // Try to upload to the 'references' facet which has the 100MB limit
6679+
// String referencesFacet = "references";
6680+
// List<String> createResponse =
6681+
// api.createAttachment(
6682+
// appUrl, entityName, referencesFacet, testEntityID, srvpath, postData, file);
6683+
// String check = createResponse.get(0);
6684+
6685+
// // The upload should fail with AttachmentSizeExceeded error
6686+
// if (!check.equals("Attachment created")) {
6687+
// try {
6688+
// JSONObject json = new JSONObject(check);
6689+
// String errorCode = json.getJSONObject("error").getString("code");
6690+
// String errorMessage = json.getJSONObject("error").getString("message");
6691+
// assertEquals("413", errorCode);
6692+
// assertEquals("File size exceeds the limit of 30MB.", errorMessage);
6693+
// } catch (Exception e) {
6694+
// fail("Failed to parse error response: " + e.getMessage());
6695+
// }
6696+
// } else {
6697+
// fail("Attachment got created with file size exceeding maximum limit");
6698+
// }
6699+
6700+
// // delete the test entity draft
6701+
// api.deleteEntityDraft(appUrl, entityName, testEntityID);
6702+
// }
66536703
}
30 MB
Binary file not shown.

0 commit comments

Comments
 (0)