So I got this gradle script that let's me upload apks to Nexus. The issue is that those files end up without file extension on the server which is a problem if you want to download an app from there.
It seems that I'm passing the proper mime type but even with that I'm still getting a file without extension.
Here is the code:
def uploadToRepository(File file,
String folder,
String url,
String userName,
String password){
HTTPBuilder http = new HTTPBuilder(url)
String basicAuthString = "Basic " + "${userName}:${password}".bytes.encodeBase64().toString()
http.client.addRequestInterceptor(new HttpRequestInterceptor() {
void process(HttpRequest httpRequest, HttpContext httpContext) {
httpRequest.addHeader('Authorization', basicAuthString)
}
})
try {
http.request(Method.POST, "application/vnd.android.package-archive") { req ->
uri.path = "/content/repositories/releases/${folder}"
MultipartEntity entity = new MultipartEntity()
def fileBody = new FileBody(file, "application/vnd.android.package-archive")
entity.addPart("file", fileBody)
req.entity = entity
response.success = { resp, reader ->
if(resp.status == 201) {
println "File ${file.name} uploaded"
}
}
}
} catch (Exception e) {
e.printStackTrace()
}
}
Related
I am trying change filename for IFormFile before uploading it to azure blob storage but my current solution is not working
public async Task<ExecuteResult> UploadAsync(string name, IFormFile file, CancellationToken cancellationToken)
{
try
{
using (var fileStream = new FileStream(Path.Combine("", name), FileMode.Create))
{
await file.CopyToAsync(fileStream);
}
BlobClient client = _client.GetBlobClient(file.FileName);
await using (Stream? data = file.OpenReadStream())
{
await client.UploadAsync(data, true, cancellationToken);
}
return ExecuteResult.Success();
}
catch (RequestFailedException ex)
when (ex.ErrorCode == BlobErrorCode.BlobAlreadyExists)
{
await UploadFileAsync(file, cancellationToken);
return ExecuteResult.Success();
}
catch (RequestFailedException ex)
{
return ExecuteResult.Fail(new Error($"Unhandled Exception. ID: {ex.StackTrace} - Message: {ex.Message}", ""));
}
}
Any suggestions on how to fix it ?
SOLUTION
The problem is my misunderstanding of the file upload, if you are interested in saving the file under a different name you should put it in the line
BlobClient client = _client.GetBlobClient($"{name}{format}");
Complete solution
public async Task<ExecuteResult> UploadAsync(string name, IFormFile file, CancellationToken cancellationToken)
{
try
{
string format = Path.GetExtension(file.FileName);
BlobClient client = _client.GetBlobClient($"{name}{format}");
await using (Stream? data = file.OpenReadStream())
{
await client.UploadAsync(data, true, new CancellationToken());
}
return ExecuteResult.Success();
}
catch (RequestFailedException ex)
{
return ExecuteResult.Fail(new Error($"Unhandled Exception. ID: {ex.StackTrace} - Message: {ex.Message}", ""));
}
}
if you want to modify the name of the file to create a sub directory in a blob container, you can do as follows:
public async Task<BlobResponseDto> UploadWithPrefixAsync(IFormFile blob, string prefix)
{
// Create new upload response object that we can return to the requesting method
BlobResponseDto response = new BlobResponseDto();
// Get a reference to a container named in appsettings.json and then create it
BlobContainerClient container = new BlobContainerClient(_storageConnectionString, _storageContainerName);
//await container.CreateAsync();
try
{
// Get a reference to the blob just uploaded from the API in a container from configuration settings
BlobClient client = container.GetBlobClient($"{prefix}" + blob.FileName);
// Open a stream for the file we want to upload
await using (Stream? data = blob.OpenReadStream())
{
// Upload the file async
await client.UploadAsync(data);
}
// Everything is OK and file got uploaded
response.Status = $"File {blob.FileName} Uploaded Successfully";
response.Error = false;
response.Blob.Uri = client.Uri.AbsoluteUri;
response.Blob.Name = client.Name;
}
// If the file already exists, we catch the exception and do not upload it
catch (RequestFailedException ex)
when (ex.ErrorCode == BlobErrorCode.BlobAlreadyExists)
{
_logger.LogError($"File with name {blob.FileName} already exists in container. Set another name to store the file in the container: '{_storageContainerName}.'");
response.Status = $"File with name {blob.FileName} already exists. Please use another name to store your file.";
response.Error = true;
return response;
}
// If we get an unexpected error, we catch it here and return the error message
catch (RequestFailedException ex)
{
// Log error to console and create a new response we can return to the requesting method
_logger.LogError($"Unhandled Exception. ID: {ex.StackTrace} - Message: {ex.Message}");
response.Status = $"Unexpected error: {ex.StackTrace}. Check log with StackTrace ID.";
response.Error = true;
return response;
}
// Return the BlobUploadResponse object
return response;
}
My inspiration for this solution came after reading this great article of Christian Schou.
Happy coding!
Project setup:
<java.version>1.8</java.version>
<spring.version>4.3.9.RELEASE</spring.version>
<spring.boot.version>1.4.3.RELEASE</spring.boot.version>
We have a REST controller that has a method to upload file like this:
#PostMapping("/spreadsheet/upload")
public ResponseEntity<?> uploadSpreadsheet(#RequestBody MultipartFile file) {
if (null == file || file.isEmpty()) {
return new ResponseEntity<>("please select a file!", HttpStatus.NO_CONTENT);
} else if (blueCostService.isDuplicateSpreadsheetUploaded(file.getOriginalFilename())) {
return new ResponseEntity<>("Duplicate Spreadsheet. Please select a different file to upload",
HttpStatus.CONFLICT);
} else {
try {
saveUploadedFiles(Arrays.asList(file));
} catch (IOException e) {
e.printStackTrace();
return new ResponseEntity<>(HttpStatus.BAD_REQUEST);
}
return new ResponseEntity("Successfully uploaded - " + file.getOriginalFilename(), new HttpHeaders(),
HttpStatus.OK);
}
}
UPDATE:
I've tried this approach from an old example I found, but it doesn't compile cleanly, the MockMvcRequestBuilders.multipart method is not defined....
#Test
public void testUploadSpreadsheet_Empty() throws Exception {
String fileName = "EmptySpreadsheet.xls";
String content = "";
MockMultipartFile mockMultipartFile = new MockMultipartFile(
"emptyFile",
fileName,
"text/plain",
content.getBytes());
System.out.println("emptyFile content is '" + mockMultipartFile.toString() + "'.");
mockMvc.perform(MockMvcRequestBuilders.multipart("/bluecost/spreadsheet/upload")
.file("file", mockMultipartFile.getBytes())
.characterEncoding("UTF-8"))
.andExpect(status().isOk());
}
I believe MockMvcRequestBuilders.multipart() is only available since Spring 5. What you want is MockMvcRequestBuilders.fileUpload() that is available in Spring 4.
I have been fighting with this issue since last week.still not able to solve.
i am sending file to client machine once i get in server automatically.but so many time when i handle file it throw an error that Cannot access the file because it is using by another program.
below my code
private static string SaveFileStream(string filePath, Stream stream, string Filename1)
{
string localresponse;
try
{
//this.SaveFileStream(System.Configuration.ConfigurationSettings.AppSettings[fileToPush.FileType].ToString() + "\\" + fileToPush.FileName, new MemoryStream(fileToPush.Content));
if (File.Exists(filePath))
{
File.Delete(filePath);
}
using (var fileStream = new FileStream(filePath, FileMode.Create, FileAccess.Write))
{
stream.CopyTo(fileStream);
fileStream.Flush();
fileStream.Dispose();
}
FileInfo info = new FileInfo(filePath);
ExtractFile(info);
localresponse = "Successful";
}
catch (Exception ex)
{
localresponse = ex.Message;
}
return localresponse;
}
I our app (Xamarin C#) we download files from a server. At the end of a succeful download we get the URI to the newly-downloaded file and from the URI we get the file path:
Android.Net.Uri uri = downloadManager.GetUriForDownloadedFile(entry.Value);
path = u.EncodedPath;
In Android 4.4.2 and in Android 5 the uri and path look like this:
uri="file:///storage/emulated/0/Download/2.zip"
path = u.EncodedPath ="/storage/emulated/0/Download/2.zip"
We then use path to process the file.
The problem is that in Android 6 (on a real Nexus phone) we get a completely different uri and path:
uri="content://downloads/my_downloads/2802"
path="/my_downloads/2802"
This breaks my code by throwing a FileNotFound exception. Note that the downloaded file exists and is in the Downloads folder.
How can I use the URI I get from Android 6 to get the proper file path so I can to the file and process it?
Thank you,
donescamillo#gmail.com
I didn't get your actual requirement but it looks like you want to process file content. If so it can be done by reading the file content by using file descriptor of downloaded file. Code snippet as
ParcelFileDescriptor parcelFd = null;
try {
parcelFd = mDownloadManager.openDownloadedFile(downloadId);
FileInputStream fileInputStream = new FileInputStream(parcelFd.getFileDescriptor());
} catch (FileNotFoundException e) {
Log.w(TAG, "Error in opening file: " + e.getMessage(), e);
} finally {
if(parcelFd != null) {
try {
parcelFd.close();
} catch (IOException e) {
}
}
}
But I am also looking to move or delete that file after processing.
May you an build your URI with the download folder :
Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS).toURI();
It's work. #2016.6.24
#Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if(DownloadManager.ACTION_DOWNLOAD_COMPLETE.equals( action)) {
DownloadManager downloadManager = (DownloadManager)context.getSystemService(Context.DOWNLOAD_SERVICE);
long downloadId = intent.getLongExtra(DownloadManager.EXTRA_DOWNLOAD_ID, 0);
DownloadManager.Query query = new DownloadManager.Query();
query.setFilterById(downloadId);
Cursor c = downloadManager.query(query);
if(c != null) {
if (c.moveToFirst()) {
int columnIndex = c.getColumnIndex(DownloadManager.COLUMN_STATUS);
if (DownloadManager.STATUS_SUCCESSFUL == c.getInt(columnIndex)) {
String downloadFileUrl = c.getString(c.getColumnIndex(DownloadManager.COLUMN_LOCAL_URI));
startInstall(context, Uri.parse(downloadFileUrl));
}
}
c.close();
}
}
}
private boolean startInstall(Context context, Uri uri) {
if(!new File( uri.getPath()).exists()) {
System.out.println( " local file has been deleted! ");
return false;
}
Intent intent = new Intent();
intent.addFlags( Intent.FLAG_ACTIVITY_NEW_TASK);
intent.setAction( Intent.ACTION_VIEW);
intent.setDataAndType( uri, "application/vnd.android.package-archive");
context.startActivity( intent);
return true;
}
I have a case where I need to call several different web endpoints and need to do the same setup and tear down for every call. I am trying to write a more generic method where I can pass in the method I want to execute along with the package to send to the endpoint and expect a string return.
From my code I can make this call:
var ret = WebServiceHandler.Execute(WebServiceHandler.LoadNewAsset(package));
The definition of Execute looks like:
internal static string Execute<T>(Func<T, string> executeThisAction)
{
Func<T, string> resp;
Setup();
resp = executeThisAction;
CleanUp();
return resp.ToString();
}
This is one of the methods I want to execute:
internal static Func<CarsWS_AssetLoad, string> LoadNewAsset(AssetLoad package)
{
string resp;
try
{
// Make the web service call...
var assetLoadReturn = _service.LoadNewAsset(new LoadNewAssetRequest {UserCredentialsHeader = _credentials, asset = package});
// Evaluate results...
if (assetLoadReturn.LoadNewAssetResult.responseType == "Success")
resp = (result != null && !String.IsNullOrEmpty(result.asset.assetID))
? "Got assetID: " + result.asset.assetID
: "No assetID returned.";
else
resp = result.responseDescription.Trim();
}
catch (Exception ex)
{
resp = "Error calling LoadNewAsset()." + Environment.NewLine + ex.GetFullMessage();
}
return resp; // <== THIS IS NOT A VALID RETURN <== //
}
My brain is shutting off at this point. How do I return the string back up the call stack correctly???
I assume that in your LoadNewAsset method the CarsWS_AssetLoad class is actually the same as AssetLoad and it was just a editing issue with your question.
That being the case, I think this is what you want:
internal static string Execute<T>(Func<T, string> executeThisAction, AssetLoad package)
{
string resp;
Setup();
resp = executeThisAction(package);
CleanUp();
return resp;
}
internal static Func<AssetLoad, string> LoadNewAsset()
{
return package =>
{
string resp;
var assetLoadReturn = _service.LoadNewAsset(new LoadNewAssetRequest {UserCredentialsHeader = _credentials, asset = package});
if (assetLoadReturn.LoadNewAssetResult.responseType == "Success")
resp = (result != null && !String.IsNullOrEmpty(result.asset.assetID))
? "Got assetID: " + result.asset.assetID
: "No assetID returned.";
else
resp = result.responseDescription.Trim();
return resp;
};
}
The use of the variable result in the LoadNewAsset is a little confusing too. Did you mean to use LoadNewAsset instead?
The above code should be able to workable for you, but it's really not the right way to go about coding this.
I assume that the Setup & CleanUp code is all about instantiating the _service that you're calling?
So the key is to code it this way:
internal static string Execute<T>(Func<IAssetService, T, string> serviceCall, AssetLoad package)
{
string resp;
var service = Setup();
resp = serviceCall(service, package);
CleanUp(service);
return resp;
}
internal static Func<IAssetService, AssetLoad, string> GetLoadNewAssetFunc()
{
return (service, package) =>
{
string resp;
var assetLoadReturn = service.LoadNewAsset(new LoadNewAssetRequest {UserCredentialsHeader = _credentials, asset = package});
if (assetLoadReturn.LoadNewAssetResult.responseType == "Success")
resp = (result != null && !String.IsNullOrEmpty(result.asset.assetID))
? "Got assetID: " + result.asset.assetID
: "No assetID returned.";
else
resp = result.responseDescription.Trim();
return resp;
};
}
Ideally if you would bring the Setup & CleanUp code into the Execute method so that the only way to call the set-up and clean-up code is thru the Execute method.
Even better, if the service class implements IDisposable then your execute code would look like this:
internal static string Execute<T>(Func<IAssetService, T, string> serviceCall, AssetLoad package)
{
using (var service = Setup())
{
return serviceCall(service, package);
}
}
Let me know if I've missed anything.
Replace:
internal static string Execute<T>(Func<T, string> executeThisAction)
with
internal static string Execute<T>(Func<T, string> executeThisAction, T argument)
then replace:
internal static Func<CarsWS_AssetLoad, string> LoadNewAsset(AssetLoad package)
with
internal static string LoadNewAsset(AssetLoad package)
then to call it:
var ret = WebServiceHandler.Execute(WebServiceHandler.LoadNewAsset, package);