This question already has answers here:
How can I upload files to a server using JSP/Servlet?
(14 answers)
Closed 5 years ago.
I have to create a form using JavaScript and an user will upload a JPG file and submit along with other info such as name, email, etc. When the user clicks submit all the information from the form will be loaded to a value object. For the image file I've set it to be byte[].
So assuming:
public String name;
public String email;
public byte[] logo;
I've set up a servlet as well to handle the submission but I'm not sure how to get started. How does the upload work? When user submits, how do I get the information for the image? Here's a screenshot: http://imageshack.us/f/32/77675354.png/ I need to convert that image and save it to a byte[] then convert to blob so I can insert it to a table.
For the file upload part, you need to set enctype="multipart/form-data" on the HTML form so that the webbrowser will send the file content and you'd like to use request.getPart() in servlet's doPost() method to get the file as an InputStream. For a concrete code example, see also How to upload files to server using JSP/Servlet?
Then, to save this InputStream in the DB, just use PreparedStatement#setBinaryStream() on a BLOB/varbinary/bytea column or whatever column represents "binary data" in your favorite DB engine.
preparedStatement = connection.prepareStatement("INSERT INTO user (name, email, logo) VALUES (?, ?, ?)");
preparedStatement.setString(1, name);
preparedStatement.setString(2, email);
preparedStatement.setBinaryStream(3, logo);
// ...
You don't necessarily need to convert this InputStream to byte[], it would not have been memory efficient either. Imagine that 100 user simultaneously upload images of 10MB, then 1GB of server memory would have been allocated at that point.
You probably should not be storing an image in a database. The database is literally the most expensive place where you can store binary data. DB size will grow fast and querying cost is high. You might end up with non-scalable and barely efficient solution of image hosting.
Store it in separate resource server, like Amazon S3 or anywhere else (local Nginx, Tomcat etc).
Instead you can store unique file names and/or full path to the file. In such a way you'll facilitate DB's workload and columns data will be readable, so you can quickly find desired picture. I'm not even talking about performance in general, simple benchmark will easily prove it.
Related
I'm working in Spring Boot project where I have two entities.
Client entity :
#Entity
public class Client {
// mapping annotation ...
private Long id;
// mapping annotation ...
private String firstName;
// mapping annotation ...
private String lastName;
// mapping annotation ...
private Set<Document> listDocument;
....
}
Document entity :
#Entity
public class Document{
// mapping annotation ...
private Long id;
// mapping annotation ...
private String name;
// mapping annotation ...
private int size;
// mapping annotation ...
private Client client;
....
}
My app has a form where I set all the information of the clients. Also, I have an input file where I have to upload multiple documents.So, when I click on submit button I have to persist the client information into the database along with all information (doc name,size..) about documents (with client Id) should be persisted in database and then files to be uploaded to the server.
I'm using Spring Boot with Angular, I'm not asking for code but I just want to know what will the best approach to achieve this according to the best practices.
I also had a similar Use Case. We have done this with File Zipping approach (require less storage, fast for small documents ). When the Client uploads the documents we create the new Zip file and named it in a unique way.
(not changing the names of original documents). For example, you can give a unique name with clientID + uploadTime.
Now to store there can be multiple ways (for rapid document retrieval)
Create only one directory (not an ideal way)
Create directories according to ClientId
Create directories according to UploadTime (DayWise, MonthWise)
If all the documents are uploaded successfully then you can save the information of documents in the table. Note that storing the path of a document can create a problem if the path changes in future so store only name of the document. As here you need to store details of each document you can create two tables. One table with id(pk), client Id, zip filename another with id(fk), document name, size etc.
you can configure max file-size, max request-size as below in application properties
MULTIPART (MultipartProperties)
spring.servlet.multipart.enabled=true # Whether to enable support of multipart uploads.
spring.servlet.multipart.file-size-threshold=0B # Threshold after which files are written to disk.
spring.servlet.multipart.location= # Intermediate location of uploaded files.
spring.servlet.multipart.max-file-size=1MB # Max file size.
spring.servlet.multipart.max-request-size=10MB # Max request size.
spring.servlet.multipart.resolve-lazily=false # Whether to resolve the multipart request lazily at the time of file or parameter access.
I did not understand the essense of the question.
In my opinion, it's necessary to upload files to the storage first. Operation of upload should be transactional (all or nothing). Error during any file upload fail whole upload. If the upload was successful - then save the information about files to the database.
I suggest to store the following additional information about uploaded files:
Date and time the file was uploaded
Id of the request. To know that multiple files have been uploaded within one request. You can use time in millis System.currentTimeMillis() or UUID UUID.randomUUID().toString()
Also, if the system contains a lot of files - I recommend storing files in separate directories to speed up the search. You can store to directories by the time of creation (for example every month new directory), or by the user id. It all depends on the search criteria for the files.
I would recommend you to rename files before store with any unique id (UUID for example) to avoid collisions. Of course you should store original and renamed file names in the database. Also this approach will not allow user to pick up the file name if the directory with files will be open. I mean that users can't guess alien files https://file-storage/user-john-dou/logo.jpg
If you are working with images you can think about resize before store.
So I am working on this project where I want to store an audio file in a LARGEBLOB on a database, the size of the file is limited to about 10MB, and be able to load the data through a java servlet that allows for playing of the media file.
Most of the sources I have been able to find suggests storing it locally, however, I want to avoid this solution based on the fact that I'd like to rebuild the website somewhere completely different and not have to rely on the folder structure to be the same.
The issues that I am encountering area mainly that the web browser misinterprets the binary data provided by the servlet. It manages to retrieve that it is an audio file of some sort, however; it is unable to determine the type of audio file, which leads me to believe that the servlet is either not providing enough data, or that I am not doing enough to instruct the web browser on how to play the file.
For example, if I have a file audio.mp3 which I have uploaded to the database into a table Tracks and stored in a column TrackFile. Assuming the query of selecting the right song from the table, what data would the servlet need to provide in order for the browser to play the file when accessing the servlet. Currently when I load the servlet, the browser seems to assume that the type is audio/mpeg instead of audio/mp3. The content currently delivered by the servlet also looks something like this:
response.setHeader("Content-Type", this.getServletContext().getMimeType(t.getTrackName() + '.' + t.getFileType()));
response.setHeader("Content-Length", String.valueOf(t.getTrackData().length));
response.setHeader("Content-Disposition", "inline; filename=\"" + t.getTrackName() + '.' + t.getFileType() + "\"");
response.getOutputStream().write(t.getTrackData());
where t is an object which holds all the data which can be retrieved from the database table about a specific track. The method getTrackData() returns a byte[] with contents of the column TrackFile in it. The source of this method is: link, although I adapted it in order to make it work with audio files, although it doesn't.
Are there any obvious things that I should have caught onto based on the fact that I can't get it to play back the file or is what I want to achieve generally impossible so to say?
I have never saved and retrieved an image to and from the database before. I wrote down what I guessed would be the process. I would just like to know if this is correct though:
Save image:
Select & Upload image file from jsp (Struts 2) which will save it as a .tmp file.
Convert the .tmp file to a byte[] array (Java Server-Side)
Store the byte[] array as a blob in the database (Java Server-Side)
Get image:
Get the byte[] array from the database (Java Server-Side)
Convert the byte[] array to an image file (Java Server-Side)
Create the file in a location (Java Server-Side)
Use an img tag to display the file (JSP Client-Side)
Delete the file after it's finished being used? (Java Server-Side)
I'm aware of the fact that it is highly recommended to not save & retrieve images to and from the database. I would like to know how to do it anyway.
Thanks
Almost correct.
It's expensive and not so great to create the file on the fly and then delete it.
Yes, you store it as the raw bytes in the database, but the way to retrieve it and display it to a client machine is to implement a web handler that sets the content-type of the response to the appropriate MIME type and then dumps the bytes out to the response stream.
Yes, You get it right.
Save Image :
The decision to save image is very much dependent on further usage. You have one option to save the file on the file system. The location for saved file should be saved into the metadata in the database table.
Get Image:
You do not have to right file data on any temp location. It can be easily rendered from the database only. Just send a request from client and intercept that request in a spacial designed Servlet. This Servlet will read the file metadata and corresponding file, if successful, write the file back on the response stream.
I have a Struts2 jsp page their i am sending one image, Temporary file path is comming to my java class after form submission but i do not know how can to save that path in db by changing it to Blob type.. Please consider this image columns is of blob type in my database table..
Here is the output what am getting in my Javaclass after the form submission:
My image path:
F:\Documents and Settings\software.netbeans\7.0\apache-tomcat-7.0.11_base\work\Catalina\localhost\AIGSA\upload__214d4f3e_136e8b74d9c__7fff_00000021.tmp 105542
filenames:
* Winter.jpg
Code:
for (File u: repImage)
{
System.out.println("*** "+u+"\t"+u.length());
}
int saveToDb= mo.addMembers(memberName, repImage);
How can I send my form Image to this {repImage Name, so that it will be easy to save it so my db
am not sure, but try:
int saveToDb= mo.addMembers( memberName, repImage.getBytes() );
If I understand your question properly, you want to store the binary data in your database. I'd say this is a bad idea in the first place for multiple reasons. A better method would be to reference a relative path that you can then use in your web application or the file system directly. Better yet, just store the reference to the location in Amazon/S3 where you want to save it/use it.
Regardless, to answer your question you would want to use ByteArrayOutputStream.
I have web service which receives 100 Mb video file by chunks
public void addFileChunk(Long fileId, byte[] buffer)
How can I store this file in Postgresql database using hibernate?
Using regular JDBC is very straight forward. I would use the following code inside my web service method:
LargeObject largeObject = largeObjectManager.Open(fileId, LargeObjectManager.READWRITE);
int size = largeObject.Size();
largeObject.Seek(size);
largeObject.Write(buffer);
largeObject.Close();
How can I achieve the same functionality using Hibernate? and store this file by chunk?
Storing each file chunk in separate row as bytea seems to me not so smart idea. Pease advice.
its now advisable to store 100MB files in database. I would instead store them in the filesystem, but considering transactions are active, employing Servlets seems reasonable.
process http request so that file (received one) is stored in some temporal location.
open transaction, persist file metadata including temporal location, close transaction
using some external process which will monitor temporal files, transfer this file to its final destination from which it will be available to user through some Servlet.
see http://in.relation.to/Bloggers/PostgreSQLAndBLOBs
Yeah byteas would be bad. Hibernate has a way to continue to use large objects and you get to keep the streaming interface.