diff --git a/src/App/Pages/Send/SendAddEditPage.xaml b/src/App/Pages/Send/SendAddEditPage.xaml
index bf2871e5a..98adc268b 100644
--- a/src/App/Pages/Send/SendAddEditPage.xaml
+++ b/src/App/Pages/Send/SendAddEditPage.xaml
@@ -227,7 +227,7 @@
Clicked="ChooseFile_Clicked" />
diff --git a/src/App/Pages/Vault/AttachmentsPageViewModel.cs b/src/App/Pages/Vault/AttachmentsPageViewModel.cs
index bed4ecf85..6063d2660 100644
--- a/src/App/Pages/Vault/AttachmentsPageViewModel.cs
+++ b/src/App/Pages/Vault/AttachmentsPageViewModel.cs
@@ -102,7 +102,7 @@ namespace Bit.App.Pages
AppResources.AnErrorHasOccurred);
return false;
}
- if (FileData.Length > 104857600) // 100 MB
+ if (FileData.Length > 524288000) // 500 MB
{
await _platformUtilsService.ShowDialogAsync(AppResources.MaxFileSize,
AppResources.AnErrorHasOccurred);
diff --git a/src/App/Pages/Vault/ViewPageViewModel.cs b/src/App/Pages/Vault/ViewPageViewModel.cs
index 73314c558..acf882fce 100644
--- a/src/App/Pages/Vault/ViewPageViewModel.cs
+++ b/src/App/Pages/Vault/ViewPageViewModel.cs
@@ -477,7 +477,7 @@ namespace Bit.App.Pages
await _deviceActionService.ShowLoadingAsync(AppResources.Downloading);
try
{
- var data = await _cipherService.DownloadAndDecryptAttachmentAsync(attachment, Cipher.OrganizationId);
+ var data = await _cipherService.DownloadAndDecryptAttachmentAsync(Cipher.Id, attachment, Cipher.OrganizationId);
await _deviceActionService.HideLoadingAsync();
if (data == null)
{
diff --git a/src/App/Resources/AppResources.resx b/src/App/Resources/AppResources.resx
index 95451e1b8..82858db43 100644
--- a/src/App/Resources/AppResources.resx
+++ b/src/App/Resources/AppResources.resx
@@ -926,9 +926,6 @@
Feature Unavailable
- Maximum file size is 100 MB.
-
-
Maximum file size is 500 MB.
diff --git a/src/Core/Abstractions/IApiService.cs b/src/Core/Abstractions/IApiService.cs
index 4edeba2fd..87214347b 100644
--- a/src/Core/Abstractions/IApiService.cs
+++ b/src/Core/Abstractions/IApiService.cs
@@ -46,9 +46,14 @@ namespace Bit.Core.Abstractions
Task SendAsync(HttpMethod method, string path,
TRequest body, bool authed, bool hasResponse);
void SetUrls(EnvironmentUrls urls);
- Task PostCipherAttachmentAsync(string id, MultipartFormDataContent data);
+ [Obsolete("Mar 25 2021: This method has been deprecated in favor of direct uploads. This method still exists for backward compatibility with old server versions.")]
+ Task PostCipherAttachmentLegacyAsync(string id, MultipartFormDataContent data);
+ Task PostCipherAttachmentAsync(string id, AttachmentRequest request);
+ Task GetAttachmentData(string cipherId, string attachmentId);
Task PostShareCipherAttachmentAsync(string id, string attachmentId, MultipartFormDataContent data,
string organizationId);
+ Task RenewAttachmentUploadUrlAsync(string id, string attachmentId);
+ Task PostAttachmentFileAsync(string id, string attachmentId, MultipartFormDataContent data);
Task> GetHibpBreachAsync(string username);
Task PostTwoFactorEmailAsync(TwoFactorEmailRequest request);
Task PutDeviceTokenAsync(string identifier, DeviceTokenRequest request);
diff --git a/src/Core/Abstractions/ICipherService.cs b/src/Core/Abstractions/ICipherService.cs
index 6bee873f6..f5902bf4a 100644
--- a/src/Core/Abstractions/ICipherService.cs
+++ b/src/Core/Abstractions/ICipherService.cs
@@ -35,7 +35,7 @@ namespace Bit.Core.Abstractions
Task UpdateLastUsedDateAsync(string id);
Task UpsertAsync(CipherData cipher);
Task UpsertAsync(List cipher);
- Task DownloadAndDecryptAttachmentAsync(AttachmentView attachment, string organizationId);
+ Task DownloadAndDecryptAttachmentAsync(string cipherId, AttachmentView attachment, string organizationId);
Task SoftDeleteWithServerAsync(string id);
Task RestoreWithServerAsync(string id);
}
diff --git a/src/Core/Abstractions/IFileUploadService.cs b/src/Core/Abstractions/IFileUploadService.cs
index b0da4e170..441082e5d 100644
--- a/src/Core/Abstractions/IFileUploadService.cs
+++ b/src/Core/Abstractions/IFileUploadService.cs
@@ -4,6 +4,7 @@ using Bit.Core.Models.Response;
namespace Bit.Core.Abstractions {
public interface IFileUploadService {
+ Task UploadCipherAttachmentFileAsync(AttachmentUploadDataResponse uploadData, string fileName, byte[] encryptedFileData);
Task UploadSendFileAsync(SendFileUploadDataResponse uploadData, CipherString fileName, byte[] encryptedFileData);
}
}
diff --git a/src/Core/Models/Request/AttachmentRequest.cs b/src/Core/Models/Request/AttachmentRequest.cs
index 96837545f..fd11fb541 100644
--- a/src/Core/Models/Request/AttachmentRequest.cs
+++ b/src/Core/Models/Request/AttachmentRequest.cs
@@ -6,5 +6,6 @@ namespace Bit.Core.Models.Request
{
public string FileName { get; set; }
public string Key { get; set; }
+ public long FileSize { get; set; }
}
}
diff --git a/src/Core/Models/Response/AttachmentUploadDataReponse.cs b/src/Core/Models/Response/AttachmentUploadDataReponse.cs
new file mode 100644
index 000000000..5f1a76c37
--- /dev/null
+++ b/src/Core/Models/Response/AttachmentUploadDataReponse.cs
@@ -0,0 +1,12 @@
+using Bit.Core.Enums;
+
+namespace Bit.Core.Models.Response
+{
+ public class AttachmentUploadDataResponse
+ {
+ public string AttachmentId { get; set; }
+ public FileUploadType FileUploadType { get; set; }
+ public CipherResponse CipherResponse { get; set; }
+ public string Url { get; set; }
+ }
+}
diff --git a/src/Core/Services/ApiService.cs b/src/Core/Services/ApiService.cs
index f0ea50bbd..0d69f5d9d 100644
--- a/src/Core/Services/ApiService.cs
+++ b/src/Core/Services/ApiService.cs
@@ -303,16 +303,26 @@ namespace Bit.Core.Services
#region Attachments APIs
- public Task PostCipherAttachmentAsync(string id, MultipartFormDataContent data)
+ [Obsolete("Mar 25 2021: This method has been deprecated in favor of direct uploads. This method still exists for backward compatibility with old server versions.")]
+ public Task PostCipherAttachmentLegacyAsync(string id, MultipartFormDataContent data)
{
return SendAsync(HttpMethod.Post,
string.Concat("/ciphers/", id, "/attachment"), data, true, true);
}
+ public Task PostCipherAttachmentAsync(string id, AttachmentRequest request)
+ {
+ return SendAsync(HttpMethod.Post,
+ $"/ciphers/{id}/attachment/v2", request, true, true);
+ }
+
+ public Task GetAttachmentData(string cipherId, string attachmentId) =>
+ SendAsync(HttpMethod.Get, $"/ciphers/{cipherId}/attachment/{attachmentId}", true);
+
public Task DeleteCipherAttachmentAsync(string id, string attachmentId)
{
- return SendAsync