Spring boot upload zip files slow - spring

I am using Spring boot upload files to server.I found something weird.when I upload a Jpg file with 4.88MB ,it takes 8.47s,but a 3.16M zip file,it takes about 1.3min. Considering this compressed file contains over 900 small files. I changed another zip file contains 10 small files.Now it takes 33.96s to transfer data even this new zip file is 6.52M,more lager then the old.
So does the number of files in the zip file affect the upload speed? If so, why?
application.yml:
spring:
http:
multipart:
enabled: true
max-file-size: 20MB
java:
#RequestMapping("/changeMainAttachment")
#ResponseBody
public Object addChangeMainAttachment(#RequestParam("changeMainAttachment[]") MultipartFile[] files){
String fileSavePath = gunsProperties.getFileUploadPath();
for (MultipartFile multipartFile : files) {
String fileName = UUID.randomUUID() + "#_#_#" + multipartFile.getOriginalFilename();
try {
logger.info("file uploaded to: " + fileSavePath + fileName);
multipartFile.transferTo(new File(fileSavePath + fileName));
} catch (Exception e) {
throw new BusinessException(BizExceptionEnum.UPLOAD_ERROR);
}
}
return new Msg();
}
At the front side,I use Bootstrap File-input
js:
initFileInput: function(select,_url,_showZone,_async,befordUpload,afterUploaded){
var i = $(select).fileinput({
theme: "gly",
uploadUrl: _url,
dropZoneEnabled: _showZone,
uploadAsync: _async,
showUpload: true,
showUploadedThumbs: true,
maxFileSize: 20*1024,
maxFileCount: 5,
msgFilesTooMany: "选择上传的文件数量({n}) 超过允许的最大数值{m}!",
hideThumbnailContent: true // hide image, pdf, text or other content in the thumbnail preview
});
if(befordUpload && typeof befordUpload == 'function'){
i.on('filebatchpreupload',befordUpload);
}
if(afterUploaded && typeof afterUploaded == 'function'){
i.on('filebatchuploadcomplete',afterUploaded);
}
}
I call this method by the following way
ChangeAdd.initFileInput("#changeMainAttachment", /change/changeMainAttachment", true, true, ChangeAdd.fileBeforeUpload, ChangeAdd.fileAfterUploaded);

Related

Displaying / rendering metadata in filepond--file with fileposter

I am using the fileposter plugin to successfully load and display locally-stored / previously uploaded files. An AJAX request gets the associated images files and returns an array of JSON objects representing the image data:
var imageFiles = [];
$(response.files).each(function(index, element){
let file = {
source: element.id,
options: {
type: 'local',
file: {
name: element.filename,
size: element.size,
type: element.extension
},
metadata: {
poster: element.web_path,
date: element.date_uploaded
},
}
}
imageFiles.push(file);
});
pond.setOptions({files: imageFiles});
There are some items of metadata that i have added (using the metadata plugin) that i would also like rendered with the image preview - such as date uploaded, name of person who uploaded the file etc. Is there a way of adding this? There seems to be no html/markup in the library.

Xamarin Essentials's FilePicker doesn't allow picking any files on iOS

I need to import CSV/SQLite3 files in my app to restore settings from previous offline backups. I use Xamarin.Essentials.FilePicker and it works perfectly on Android, however when trying it on iOS all the files are greyed-out and I can't select any file.
I use the following file types for Android and iOS:
var customFileType =
new Xamarin.Essentials.FilePickerFileType(new Dictionary<Xamarin.Essentials.DevicePlatform, IEnumerable<string>>
{
{ Xamarin.Essentials.DevicePlatform.iOS, new string[] {
"public.comma-separated-values-text",
"text/csv",
"comma-separated values",
"CSV document",
"csv",
"public.database",
"application/x-sqlite3",
"application/vnd.sqlite3",
"application/octet-stream",
} },
{ Xamarin.Essentials.DevicePlatform.Android, new string[] {
"text/csv",
"Comma-separated values",
"CSV document",
"application/x-sqlite3",
"application/vnd.sqlite3",
"application/octet-stream"
} },
}) ;
I've also tried adding text/plain for picking CSV files on iOS and it didn't work.
In addition, I've tried selecting PDF files using pdf and it didn't work.
I feel like I'm missing something that is not related to the MIME/UTTypes I'm putting, but I couldn't find any such thing up till now.
Any help would be appreciated.
this a weird issue that even I have faced and after scratching my head for a week I gave up(This was last year) I did not know this was still an issue in any case I would suggest you create a Bug in Essentials GitHub https://github.com/xamarin/Essentials/issues
And what you can do is for the time being use FilePicker Plugin(I am still using this): https://github.com/jfversluis/FilePicker-Plugin-for-Xamarin-and-Windows
And then use it like this :
try
{
FileData fileData = await CrossFilePicker.Current.PickFile();
if (fileData == null)
return; // user canceled file picking
string fileName = fileData.FileName;
string contents = System.Text.Encoding.UTF8.GetString(fileData.DataArray);
System.Console.WriteLine("File name chosen: " + fileName);
System.Console.WriteLine("File data: " + contents);
}
catch (Exception ex)
{
System.Console.WriteLine("Exception choosing file: " + ex.ToString());
}
This Library is marked deprecated by Gerald Versluis(Owner) but he will probably still accept PRs if needed in the future.
I hope this helps you out :)

Does the package cached_network_image reduce the amount of network bandwidth from Firestore Storage?

Currently I am reading an image URL from a firebase document that contains an Image URL from Firebase Cloud Storage, and then using the package cached_network_image to load the images to the user.
My question is, does using cached_network_image for loading images reduce the networking bandwidth since many images will be loaded from the cache and not the url? If not, then how would one achieve that?
The cached_network_image is using a cache mechanism which will check if there is a file available for the url you're providing, will use the cached version so it will definitely reduces your network usage. Here is a function from DefaultCacheManager class in cache_manager.dart in Flutter`s SDK:
Future<void> _pushFileToStream(StreamController streamController, String url,
Map<String, String> headers, bool withProgress) async {
FileInfo cacheFile;
try {
cacheFile = await getFileFromCache(url);
if (cacheFile != null) {
streamController.add(cacheFile);
withProgress = false;
}
} catch (e) {
print(
'CacheManager: Failed to load cached file for $url with error:\n$e');
}
if (cacheFile == null || cacheFile.validTill.isBefore(DateTime.now())) {
try {
await for (var response
in _webHelper.downloadFile(url, authHeaders: headers)) {
if (response is DownloadProgress && withProgress) {
streamController.add(response);
}
if (response is FileInfo) {
streamController.add(response);
}
}
} catch (e) {
assert(() {
print(
'CacheManager: Failed to download file from $url with error:\n$e');
return true;
}());
if (cacheFile == null && streamController.hasListener) {
streamController.addError(e);
}
}
}
unawaited(streamController.close());
}
As you can see if it can find the cached file using the url you're providing and the file is valid, it will use that instead of downloading.

Can I get FilePond to show previews of loaded local images?

I use FilePond to show previously uploaded images with the load functionality. The files are visible, however I don't get a preview (which I get when uploading a file).
Should it be possible to show previews for files through load?
files: [{
source: " . $profile->profileImage->id . ",
options: {
type: 'local',
}
}],
First you have to install and register File Poster and File Preview plugins and here is the example of how to register it in your code:
import * as FilePond from 'filepond';
import FilePondPluginImagePreview from 'filepond-plugin-image-preview';
import FilePondPluginFilePoster from 'filepond-plugin-file-poster';
FilePond.registerPlugin(
FilePondPluginImagePreview,
FilePondPluginFilePoster,
);
then You have to set the server.load property to your server endpoint and add a metadata property to your files object which is the link to your image on the server:
const pond = FilePond.create(document.querySelector('file'));
pond.server = {
url: '127.0.0.1:3000/',
process: 'upload-file',
revert: null,
// this is the property you should set in order to render your file using Poster plugin
load: 'get-file/',
restore: null,
fetch: null
};
pond.files = [
{
source: iconId,
options: {
type: 'local',
metadata: {
poster: '127.0.0.1:3000/images/test.jpeg'
}
}
}
];
the source property is the variable you want to send to your end point which in my case I wanted to send to /get-file/{imageDbId}.
In this case it does not matter what your endpoint in the load property returns but my guess is, we have to return a file object.

Document Image response in Spring REST Docs

I have a REST endpoint that generates random images. I'm using Spring REST Docs, but the Response is all garbled in the http-response.adoc file. Is there an easy way for Mock MVC and REST Docs to store the file somewhere so my .adoc files can reference it?
Not the perfect but working solution:
class ImageSnippet implements Snippet {
private final String filePath;
public ImageSnippet(String filePath) {
this.filePath = filePath;
}
#Override
public void document(Operation operation) throws IOException {
byte[] picture = operation.getResponse().getContent();
Path path = Paths.get(filePath);
Files.deleteIfExists(path);
Files.createDirectories(path.getParent());
Files.createFile(path);
try (FileOutputStream fos = new FileOutputStream(path.toFile())) {
fos.write(picture);
}
}
}
And usage in MockMvc test (image folder path is important):
mockMvc.perform(get("/my-profile/barcode")
.accept(MediaType.IMAGE_PNG))
.andExpect(status().isOk())
.andDo(document("my-profile/barcode",
new ImageSnippet("build/asciidoc/html5/images/barcode.png")));
In .adoc template:
image::barcode.png[]
And here is my build.gradle Asciidoctor configuration (imagesdir is important):
asciidoctor {
dependsOn test
backends = ['html5']
options doctype: 'book'
attributes = [
'source-highlighter': 'highlightjs',
'imagesdir' : './images',
'toc' : 'left',
'toclevels' : 3,
'numbered' : '',
'icons' : 'font',
'setanchors' : '',
'idprefix' : '',
'idseparator' : '-',
'docinfo1' : '',
'safe-mode-unsafe' : '',
'allow-uri-read' : '',
'snippets' : snippetsDir,
linkattrs : true,
encoding : 'utf-8'
]
inputs.dir snippetsDir
outputDir 'build/asciidoc'
sourceDir 'src/docs/asciidoc'
sources {
include 'index.adoc'
}
}
What you can do is implement a custom Snippet which saves the resulting response. You can use the RestDocumentationContext attribute of the operation you receive to obtain the output directory.
mockMvc.perform(get("/example"))
.andDo(document("some-example", operation -> {
var context = (RestDocumentationContext) operation.getAttributes().get(RestDocumentationContext.class.getName());
var path = Paths.get(context.getOutputDirectory().getAbsolutePath(), operation.getName(), "response-file.png");
Files.createDirectories(path.getParent());
Files.write(path, operation.getResponse().getContent());
}));
However this will create a .png file in your output directory which generally isn't really useful if you have Asciidoc in a source directory that needs to embed it. So what you can instead do is create an Asciidoc file which contains custom HTML of an image tag with its source being a base64 representation of the response.
mockMvc.perform(get("/example"))
.andDo(document("some-example", operation -> {
var context = (RestDocumentationContext) operation.getAttributes().get(RestDocumentationContext.class.getName());
var path = Paths.get(context.getOutputDirectory().getAbsolutePath(), operation.getName(), "response-file.adoc");
var outputStream = new ByteArrayOutputStream();
outputStream.write("++++\n".getBytes());
outputStream.write("<img src=\"data:image/png;base64,".getBytes());
outputStream.write(Base64.getEncoder().encode(operation.getResponse().getContent()));
outputStream.write("\"/>\n".getBytes());
outputStream.write("++++\n".getBytes());
Files.createDirectories(path.getParent());
Files.write(path, outputStream.toByteArray());
}));
Although a bit more overhead in terms of space, if you use this, you don't need to mess with referencing build files from your sources.
An alternative way if you don't need/want to show the images in the docs: Use a ContentModifyingOperationPreprocessor to replace the bytes with some string that makes it clear to the readers of the documentation that there will be some image bytes in the response.
For example:
mockMvc.perform(get("/api/users/{id}/avatar", user.getId().asString())
.with(createCustomerAuth()))
.andExpect(status().isOk())
.andDo(document("get-user-avatar-example",
null,
Preprocessors.preprocessResponse(new ContentModifyingOperationPreprocessor(new ContentModifier() {
#Override
public byte[] modifyContent(byte[] originalContent, MediaType contentType) {
return "<< IMAGE BODY HERE >>".getBytes(StandardCharsets.UTF_8);
}
}))));
This generates an adoc file like this:
[source,http,options="nowrap"]
----
HTTP/1.1 200 OK
Content-Type: image/png
Content-Length: 15
Cache-Control: max-age=3600
<< IMAGE BODY HERE >>
----

Resources