How to make file downloadable from server to Front End in Spring Boot project, Created Rest API for file downloading but not functioning as expected? - spring-boot

In general, I have created rest controller for both uploading and downloading a file from front end (React) to our file system. Uploading works great, as expected. However, downloading rest api not functioning properly. it downloads only 12kb or smth like that of the file. Is there anything [configs] that I am missing in my project or what? Please help! any comment or suggestion would be appreciated thanks in advance
#GetMapping("/get")
fun getFile(#Valid data: FileDeleteDTO): ResponseEntity<Resource>{
val header = HttpHeaders()
val fileGetFromDb = baseFileUploaderAttachmentService.getByUid(data.qquuid)
if (!fileGetFromDb.isPresent)
throw FileNotFoundException()
val pathFileName = fileGetFromDb.get().filename + '.' + fileGetFromDb.get().extension
val originalFileName = fileGetFromDb.get().originalName + '.' + fileGetFromDb.get().extension
// val filePath = UPLOAD_ROOT_FOLDER + fileGetFromDb.get().path + pathFileName
val filePath = UPLOAD_ROOT_FOLDER + fileGetFromDb.get().path
// val file = File(filePath)
header.contentType = (MediaType.valueOf(fileGetFromDb.get().mime_type!!))
header.contentLength = fileGetFromDb.get().size
header.set("Content-Disposition", "attachment; filename=$originalFileName")
return ResponseEntity.ok()
.headers(header)
.body(loadFileAsResource(pathFileName,Paths.get(filePath)))
}
fun loadFileAsResource(fileName: String, fileStorageLocation: Path): Resource {
try {
val filePath = fileStorageLocation.resolve(fileName).normalize()
val resource = UrlResource(filePath.toUri())
return if (resource.exists()) {
resource
} else {
throw FileNotFoundException("File not found $fileName")
}
} catch (ex: MalformedURLException) {
throw Exception("File not found $fileName", ex)
}
}

I have no idea what happened but i have solved above problem by adding some header elements like below:
#RequestMapping(value = ["/download"], method = [RequestMethod.GET])
#Throws(IOException::class)
fun downloadFile(#Valid data: FileDeleteDTO): ResponseEntity<Any> {
val fileGetFromDb = baseFileUploaderAttachmentService.getByUid(data.qquuid)
val pathFileName = fileGetFromDb.get().filename + '.' + fileGetFromDb.get().extension
val originalFileName = fileGetFromDb.get().originalName + '.' + fileGetFromDb.get().extension
val filePath = UPLOAD_ROOT_FOLDER + fileGetFromDb.get().path + pathFileName
val file = File(filePath)
val resource = InputStreamResource(FileInputStream(file))
val headers = HttpHeaders()
headers.add("Content-Disposition", String.format("attachment; filename=\"%s\"", originalFileName))
headers.add("Cache-Control", "no-cache, no-store, must-revalidate")
headers.add("Pragma", "no-cache")
headers.add("Expires", "0")
return ResponseEntity.ok().headers(headers).contentLength(
file.length()
).contentType((MediaType.valueOf(fileGetFromDb.get().mime_type!!))).body(resource)
}
Just wondering does Cache control has impact on this issue? Where can i learn about headers?

Related

Kotlin : copy image to gallery

I am trying to copy an image that is stored in my application folder to a predefined folder in my gallery.
I started from an image sharing code..
This is my code :
val extension = when (requireNotNull(pictureResult).format) {
PictureFormat.JPEG -> "jpg"
PictureFormat.DNG -> "dng"
else -> throw RuntimeException("Unknown format.")
}
val timestamp = System.currentTimeMillis()
val namePhoto = "picture_"+timestamp+"."+extension;
val destFile = File(filesDir, namePhoto)
val folder = "/CustomFolder"
CameraUtils.writeToFile(requireNotNull(pictureResult?.data), destFile) { file ->
if (file != null) {
// Code to share - it works
/*
val context = this#PicturePreviewActivity
val intent = Intent(Intent.ACTION_SEND)
intent.type = "image/*"
val uri = FileProvider.getUriForFile(context, context.packageName + ".provider", file)
intent.putExtra(Intent.EXTRA_STREAM, uri)
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
startActivity(intent)
*/
*/
// Code to save image to gallery - doesn't work :(
val photoDirectory = File(Environment.DIRECTORY_PICTURES+folder, namePhoto)
val sourcePath = Paths.get(file.toURI())
Log.i("LOG","sourcePath : "+sourcePath.toString()) // /data/user/0/com.app.demo/files/picture_1663772068143.jpg
val targetPath = Paths.get(photoDirectory.toURI())
Log.i("LOG","targetPath : "+targetPath.toString()) // /Pictures/CustomFolder/picture_1663772068143.jpg
Files.move(sourcePath, targetPath, StandardCopyOption.REPLACE_EXISTING)
// Error here but I don't know why
} else {
Toast.makeText(this#PicturePreviewActivity, "Error while writing file.", Toast.LENGTH_SHORT).show()
}
}
How do I copy the image to a predefined folder?
Ok, I did it !
Solution :
val folder = "/CustomFolder/" // name of your folder
val timestamp = System.currentTimeMillis()
val namePicture = "picture_"+timestamp+"."+extension;
try {
val path = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES+folder);
if (!path.exists()) {
path.mkdir();
}
val pathImage = File(path,namePicture)
val stream = FileOutputStream(pathImage)
stream.write(imageByteArray).run {
stream.flush()
stream.close()
}
} catch (e: FileNotFoundException) {
e.printStackTrace()
}

How to wait for request to finish in Jmeter

I am currently new to Jmeter, and trying to create a Jmeter script to test how long a request takes to process and complete.
a) Authenticate using Token - Complete
b) Post Request - Complete - Returns 200
c) Get Request - Partially Completed
C: I am Trying to get be able to monitor this request to find out when its either completed failed etc.
I have created the Http Request Sample with a Get Request
I am able to get the Request 200 but it doesn't wait for completion
So running this in a console app, it waits for a certain time checking for status....
Is there a way to possibly write a code similar to the C# code in bean shell or groovy to wait. I was reading about while controller as well...
var result = WaitForBuildToComplete(dest, requestData, token, timeout);
static string GetStatus(string path, Token token)
{
var httpWebRequest = (HttpWebRequest)WebRequest.Create(path);
httpWebRequest.ContentType = "application/json";
httpWebRequest.Method = "GET";
AddToken(token, httpWebRequest);
WebResponse response = httpWebRequest.GetResponse();
string responseFromServer = "";
using (Stream dataStream = response.GetResponseStream())
{
StreamReader reader = new StreamReader(dataStream);
responseFromServer = reader.ReadToEnd();
}
// Close the response.
response.Close();
return responseFromServer;
}
static int WaitForBuildToComplete(string dest, RequestData requestData, Token token, int
timeout)
{
if (timeout <= 0) return 0;
var path = $"{ConfigurationManager.AppSettings[dest]}/policy?id={requestData.id}";
var startTime = DateTime.Now;
do
{
var status = GetStatus(path, token);
var msg = JsonConvert.DeserializeObject<string>(status);
var requestStatus = JsonConvert.DeserializeObject<RequestStatus>(msg);
if (!string.IsNullOrEmpty(requestStatus.DllUrl))
{
Console.WriteLine($"\nResult dll at: {requestStatus.DllUrl}");
return 0;
}
if (requestStatus.Status.ToUpper() == "FAILED")
{
Console.WriteLine($"\nFAILED");
Console.WriteLine(requestStatus.Message);
return -1;
}
if (requestStatus.Status.ToUpper() == "FAILED_DATA_ERROR")
{
Console.WriteLine($"\nFAILED_DATA_ERROR");
Console.WriteLine(requestStatus.Message);
return -1;
}
if (requestStatus.Status.ToUpper() == "NOT_NEEDED")
{
Console.WriteLine($"\nNOT_NEEDED");
Console.WriteLine(requestStatus.Message);
return -1;
}
Console.Write(".");
System.Threading.Thread.Sleep(1000);
} while ((DateTime.Now - startTime).TotalSeconds < timeout);
Console.WriteLine("Time out waiting for dll.");
return -1;
}
I started by looking at JSR223 Sampler but wanted to see if there is a better and easier way to accomplish this.
List<String> sendRequest(String url, String method, Map<String,Object> body) {
RequestConfig requestConfig = RequestConfig.custom()
.setConnectTimeout(2000)
.setSocketTimeout(3000)
.build();
StringEntity entity = new StringEntity(new Gson().toJson(body), "UTF-8");
HttpUriRequest request = RequestBuilder.create(method)
.setConfig(requestConfig)
.setUri(url)
.setHeader(HttpHeaders.CONTENT_TYPE, "application/json;charset=UTF-8")
.setEntity(entity)
.build();
String req = "REQUEST:" + "\n" + request.getRequestLine() + "\n" + "Headers: " +
request.getAllHeaders() + "\n" + EntityUtils.toString(entity) + "\n";
HttpClientBuilder.create().build().withCloseable {httpClient ->
httpClient.execute(request).withCloseable {response ->
String res = "RESPONSE:" + "\n" + response.getStatusLine() + "\n" + "Headers: " +
response.getAllHeaders() + "\n" +
(response.getEntity() != null ? EntityUtils.toString(response.getEntity()) : "") + "\n";
System.out.println(req + "\n" + res );
return Arrays.asList(req, res);
}
}
}
List sendGet(String url, Map<String,String> body) {
RequestConfig requestConfig = RequestConfig.custom()
.setConnectTimeout(2000)
.setSocketTimeout(3000)
.build();
RequestBuilder requestBuilder = RequestBuilder.get()
.setConfig(requestConfig)
.setUri(url)
.setHeader(HttpHeaders.CONTENT_TYPE, "application/json;charset=UTF-8");
body.forEach({key, value -> requestBuilder.addParameter(key, value)});
HttpUriRequest request = requestBuilder.build();
String req = "REQUEST:" + "\n" + request.getRequestLine() + "\n" + "Headers: " +
request.getAllHeaders() + "\n";
HttpClientBuilder.create().build().withCloseable {httpClient ->
httpClient.execute(request).withCloseable {response ->
String res = "RESPONSE:" + "\n" + response.getStatusLine() + "\n" + "Headers: " +
response.getAllHeaders() + "\n" +
(response.getEntity() != null ? EntityUtils.toString(response.getEntity()) : "") + "\n";
System.out.println(req + "\n" + res );
return Arrays.asList(req, res);
}
}
}
The approach which is normally used in JMeter is placing your request under the While Controller which will be checking the Status value which in its turn can be fetched from the response using a suitable Post-Processor so the request will be retried unless the "Status" changes to some value which you expect (or times out)
If you place the whole construction under the Transaction Controller you will get the whole time for the status to change.
Example test plan outline:

how to add a folder in the apk

I wanna to know how to add a folder in the apk.don't give me a solution about using the compress software directly. The apk was recompiled by the 'apktool.jar'. I need some code to achieve this problem. Hope one can solve my question as soon as possible.Thank you~
public static int zipMetaInfFolderToApk(String apkName, String folderName) throws IOException {
if(!new File(apkName).exists()){
return ConstantValue.ISQUESTION;
}
String zipName = apkName.substring(0, apkName.lastIndexOf(".")) + "."
+ "zip";
String bak_zipName = apkName.substring(0, apkName.lastIndexOf("."))
+ "_bak." + "zip";
FileUtils.renameFile(apkName, zipName);
ZipFile war = new ZipFile(zipName);
ZipOutputStream append = new ZipOutputStream(new FileOutputStream(
bak_zipName));
Enumeration<? extends ZipEntry> entries = war.entries();
while (entries.hasMoreElements()) {
ZipEntry e = entries.nextElement();
System.out.println("copy: " + e.getName());
append.putNextEntry(e);
if (!e.isDirectory()) {
copy(war.getInputStream(e), append);
}
append.closeEntry();
}
String name = "";
if(folderName.equals("")){
name = "META-INF/" + folderName;
}else{
name = "META-INF/" + folderName + "/";
}
ZipEntry e = new ZipEntry(name);
try{
append.putNextEntry(e);
}catch(ZipException e1){
append.closeEntry();
war.close();
append.close();
FileUtils.renameFile(zipName,apkName);
FileUtils.deleteFolder(bak_zipName);
e1.printStackTrace();
return ConstantValue.ISQUESTION;
}
append.closeEntry();
war.close();
append.close();
FileUtils.deleteFolder(zipName);
FileUtils.renameFile(bak_zipName, apkName);
return ConstantValue.ISNORMAL;
}

Issue in reading google text document

I could get the handle to the google text doc i needed. I am now stuck at how to read the contents.
My code looks like:
GoogleOAuthParameters oauthParameters = new GoogleOAuthParameters();
oauthParameters.setOAuthConsumerKey(Constants.CONSUMER_KEY);
oauthParameters.setOAuthConsumerSecret(Constants.CONSUMER_SECRET);
oauthParameters.setOAuthToken(Constants.ACCESS_TOKEN);
oauthParameters.setOAuthTokenSecret(Constants.ACCESS_TOKEN_SECRET);
DocsService client = new DocsService("sakshum-YourAppName-v1");
client.setOAuthCredentials(oauthParameters, new OAuthHmacSha1Signer());
URL feedUrl = new URL("https://docs.google.com/feeds/default/private/full/");
DocumentQuery dquery = new DocumentQuery(feedUrl);
dquery.setTitleQuery("blood_donor_verification_template_dev");
dquery.setTitleExact(true);
dquery.setMaxResults(10);
DocumentListFeed resultFeed = client.getFeed(dquery, DocumentListFeed.class);
System.out.println("feed size:" + resultFeed.getEntries().size());
String emailBody = "";
for (DocumentListEntry entry : resultFeed.getEntries()) {
System.out.println(entry.getPlainTextContent());
emailBody = entry.getPlainTextContent();
}
Plz note that entry.getPlainTextContent() does not work and throws object not TextContent type exception
finally i solved it as:
for (DocumentListEntry entry : resultFeed.getEntries()) {
String docId = entry.getDocId();
String docType = entry.getType();
URL exportUrl =
new URL("https://docs.google.com/feeds/download/" + docType
+ "s/Export?docID=" + docId + "&exportFormat=html");
MediaContent mc = new MediaContent();
mc.setUri(exportUrl.toString());
MediaSource ms = client.getMedia(mc);
InputStream inStream = null;
try {
inStream = ms.getInputStream();
int c;
while ((c = inStream.read()) != -1) {
emailBody.append((char)c);
}
} finally {
if (inStream != null) {
inStream.close();
}
}
}

AJAX file upload reloading application

I have the following snippet
class PresentationUpload {
def uploadForm(form:NodeSeq) : NodeSeq = {
var fileHolder: Box[FileParamHolder] = Empty
def handleFile() = {
fileHolder.map { holder =>
val filePath = "src/main/webapp/files"
val oFile = new File(filePath, holder.fileName)
val output = new FileOutputStream(oFile)
output.write(holder.file)
output.close()
} openOr {
// Do something
}
}
val bindForm = "type=file" #> fileUpload((fph) => fileHolder = Full(fph)) &
"type=submit" #> ajaxSubmit("Submit", handleFile _)
ajaxForm(bindForm(form))
}
}
The file uploads correctly but then reloads the application, is this the correct way to handle ajax uploads or is there another method I should be using?
Thanks for any help, much appreciated
I've configured the lift project (normally "project/build/LiftProject.scala") to not reload after changes to the files directory, problem solved :)
override def scanDirectories = (
temporaryWarPath / "WEB-INF" * ("classes" | "lib")
).get.toSeq

Resources