Hi to you all java experts.
I have this piece of code I could finally put together that works: (it's mostly java with a little ADF code)
public String upload(){
UploadedFile myfile = this.getFile();
FacesContext fctx = FacesContext.getCurrentInstance();
ServletContext servletCtx =
(ServletContext)fctx.getExternalContext().getContext();
String imageDirPath = servletCtx.getRealPath("/");
String nomdefichier = myfile.getFilename();
String mimetype = nomdefichier.substring(nomdefichier.length() - 3);
try {
InputStream inputStream = myfile.getInputStream();
BufferedImage input = ImageIO.read(inputStream);
File outputFile =
new File( System.getProperty("user.home") + File.separator + this.path + File.separator + nomdefichier);
ImageIO.write(input, mimetype, outputFile);
} catch (Exception ex) {
// handle exception
}
FacesMessage message =
new FacesMessage(mimetype + "Successfully uploaded file " + nomdefichier +
" (" + myfile.getLength() + " bytes)" + mimetype);
fctx.addMessage(null, message);
return null;
}
This codes uploads a picture just fine. I would really like to know if there is a file equivalent to ImageIO.write so that I could upload PDF, DOCX and such.
Thanks in advance for any response.
Best regards.
Marc Arbour
A simplified version of your code could be written as follows (omitting some of the JSF related stuff).
InputStream in = myFile.getInputStream();
Files.copy(in, Paths.get(yourPath));
You can write a byte array or an InputStream to a file with the java.nio.file.Files class (since Java 1.7).
// Saving data from an inputstream to a file:
Files.copy(inputStream, targetPath, copyOptions...);
// Saving a byte array to a file:
Files.write(path, byteArray, openOptions...);
Related
I have a simple Spring Boot microservice that takes care of uploading, retrieving and deleting images to/from Google Cloud Storage. I have the following code for the get request in my service:
public StorageObject getImage(String fileName) throws IOException {
StorageObject object = storage.objects().get(bucketName, fileName).execute();
File file = new File("./" + fileName);
FileOutputStream os = new FileOutputStream(file);
storage.getRequestFactory()
.buildGetRequest(new GenericUrl(object.getMediaLink()))
.execute()
.download(os);
object.set("file", file);
return object;
}
And this is my controller part:
#GetMapping("/get/image/{id}")
public ResponseEntity<byte[]> getImage(#PathVariable("id") Long id) {
try {
String fileName = imageService.findImageById(id);
StorageObject object = gcsService.getImage(fileName);
byte[] res = Files.toByteArray((File) object.get("file"));
return ResponseEntity.ok()
.contentType(MediaType.IMAGE_JPEG)
.body(res);
} catch (IOException e) {
e.printStackTrace();
throw new RuntimeException("No such file or directory");
}
}
It all works fine in terms of getting the image in the response, but my problem is that the images get downloaded at the root directory of the project too. Many images are going to be uploaded through this service so this is an issue. I only want to display the images in the response (as a byteArray), without having them download. I tried playing with the code but couldn't manage to get it to work as I want.
I'd suggest to instead stream the download, while skipping the FileChannel operation:
public static void streamObjectDownload(
String projectId, String bucketName, String objectName, String targetFile
) {
Storage storage = StorageOptions.newBuilder().setProjectId(projectId).build().getService();
try (ReadChannel reader = storage.reader(BlobId.of(bucketName, objectName));
FileChannel targetFileChannel = FileChannel.open(Paths.get(targetFile), StandardOpenOption.WRITE)) {
ByteStreams.copy(reader, targetFileChannel);
System.out.println(
"Downloaded object " + objectName
+ " from bucket " + bucketName
+ " to " + targetFile
+ " using a ReadChannel.");
}
} catch (IOException e) {
e.printStacktrace()
}
}
One can eg. obtain a FileChannel from a RandomAccessFile:
RandomAccessFile file = new RandomAccessFile(Paths.get(targetFile), StandardOpenOption.WRITE);
FileChannel channel = file.getChannel();
While the Spring framework similarly has a GoogleStorageResource:
public OutputStream getOutputStream() throws IOExceptionReturns the output stream for a Google Cloud Storage file.
Then convert from OutputStream to byte[] (this may be binary or ASCII data):
byte[] bytes = os.toByteArray();
Would it work for you to create Signed URLs in Cloud Storage to display your images? These URLs give access to storage bucket files for a limited time, and then expire, so you would rather not store temporary copies of the image locally as is suggested in this post.
I am fetching S3 objects and then sending the object in email as an attachment. I am saving the contents in a temporary file. For images the code is working fine but in case of documents (pdf, docx, csv) files the attachments are sent without extension so they are not accessible.
try {
fullObject = s3Client.getObject(new GetObjectRequest(bucketName, key));
System.out.println("fullObject: " + fullObject);
ObjectMetadata metadata = fullObject.getObjectMetadata();
System.out.println(" meta data type: " + metadata.getContentType());
InputStream inputStream = fullObject.getObjectContent();
String extension = fullObject.getKey();
int index = extension.lastIndexOf('.');
if(index > 0) {
extension = extension.substring(index + 1);
System.out.println("File extension is " + extension);
}
File file = File.createTempFile(key, "."+ extension );
System.out.println("file: "+ file);
try (OutputStream outputStream = new FileOutputStream(file)) {
IOUtils.copy(inputStream, outputStream);
} catch (Exception e) {
System.out.println("error in copying data from one file to another");
}
dataSource = new FileDataSource(file);
System.out.println("added datasource in the list");
attachmentsList.add(dataSource);
}
Upon going through this code, I got to know that the issue was not in this code but when I was setting the name of the File. I was setting filename without any extension, for example I set Filename as "temporary" this caused the documents to be saved with tmp extension. All I had to do was add the extension of the object with its name ("temporary.docx"), this solved the issue and attachments were sent properly and were accessible.
I have a web-service provider(Java), which imports a .doc file to the NotesDocument. The problem occurs with files with Russian characters in their names - they aren't correctly transferred.
For example, if the filename will be equal to Безымянный.doc, it will be transferred as Áåçûìÿííûé.doc.
File directory = new File("C:\\Attachments 1C");
String filename = "Безымянный.doc"
String path = directory + "\\" + filename;
Stream outStream = sess.createStream();
sess.setConvertMIME(true);
MIMEEntity body = newDoc.createMIMEEntity("rtBody");
Stream inStream = sess.createStream();
if (inStream.open(path, "binary")) {
if (inStream.getBytes() > 0) {
do {
byte[] buffer = inStream.read(32767);
outStream.write(buffer);
} while (!inStream.isEOS());
inStream.close();
MIMEEntity child = body.createChildEntity();
String fileSuffix = path.substring(path.lastIndexOf(".")+1);
child.setContentFromBytes(outStream, fileSuffix, MIMEEntity.ENC_IDENTITY_BINARY);
MIMEHeader header = child.createHeader("Content-Disposition");
header.setHeaderVal("attachment; filename=\"" + filename + "\"");
header = child.createHeader("Content-ID");
header.setHeaderVal(path);
outStream.truncate();
}else
return "empty file";
}else
return "couldn't open the file";
How to fix this?
The standards for this are not quite final and the behavior will depend on what browser is being used. See the question and answers to this previous question on StackOverflow for a detailed explanation and for information about what works with various browsers.
The problem is solved by encoding the filename using MimeUtility(others don't work):
String filenameEndoded = MimeUtility.encodeText(filename,"Cp1251","B");
I am uploading images and videos and creating respective tags for video and audio to display on view page but somehow image and video path are not getting resolved.
Here is my controller.
#RequestMapping(value = "/contentUpload", headers = "content-type=multipart/*", method = RequestMethod.POST)
public #ResponseBody
String uploadImage(#RequestParam("fileData") MultipartFile multipartFile, HttpServletRequest request )
{
String jsonResponse = null;
boolean isImage = false;
boolean isVideo = false;
try
{
String path = request.getServletContext().getRealPath("/");
File directory = null;
if (multipartFile.getContentType().contains("image"))
{
directory = new File(path + "/uploads/images/");
isImage = true;
}
else
{
directory = new File(path + "/uploads/videos/");
isVideo = true;
}
byte[] bytes = null;
File file = null;
bytes = multipartFile.getBytes();
if (!directory.exists()) directory.mkdirs();
file = new File(directory.getAbsolutePath() + System.getProperty("file.separator") + multipartFile.getOriginalFilename());
BufferedOutputStream stream = new BufferedOutputStream(new FileOutputStream(file));
stream.write(bytes);
stream.close();
if (isImage)
jsonResponse = "<br /><img src=\"" + file.getAbsolutePath() + "\" />";
else if (isVideo)
jsonResponse = "<video>" + "<source src=\"" + file.getAbsolutePath() + "\" type=\"" + multipartFile.getContentType() + "\">" + "</video>";
}
catch (Exception e)
{
}
return jsonResponse;
}
I have tried resources settings in dispatcher.
<mvc:resources mapping="/uploads/**" location="/#{servletContext.contextPath}/uploads/" />
uploaded image path.
/home/govi/demo/workspace/.metadata/.plugins/org.eclipse.wst.server.core/tmp0/wtpwebapps/projectImg/uploads/images/batman.jpg
please suggest me the changes required.
Use below code line, it may helps you.
<mvc:resources mapping="/uploads/**" location="/WEB-INF/projectImg/uploads/" />
'///' triple slash solved my issue. Now my resource mapping is like this.
<mvc:resources mapping="/uploads/**" location="file:///home/govi/uploads/" />
Anyone facing this issue please go through JB Nizet's comments and also go through this link How to retrieve and display images from a database in a JSP page?
I am using org.apache.commons.net.ftp.FTPClient for retrieving files from a ftp server. It is crucial that I preserve the last modified timestamp on the file when its saved on my machine. Do anyone have a suggestion for how to solve this?
This is how I solved it:
public boolean retrieveFile(String path, String filename, long lastModified) throws IOException {
File localFile = new File(path + "/" + filename);
OutputStream outputStream = new FileOutputStream(localFile);
boolean success = client.retrieveFile(filename, outputStream);
outputStream.close();
localFile.setLastModified(lastModified);
return success;
}
I wish the Apache-team would implement this feature.
This is how you can use it:
List<FTPFile> ftpFiles = Arrays.asList(client.listFiles());
for(FTPFile file : ftpFiles) {
retrieveFile("/tmp", file.getName(), file.getTimestamp().getTime());
}
You can modify the timestamp after downloading the file.
The timestamp can be retrieved through the LIST command, or the (non standard) MDTM command.
You can see here how to do modify the time stamp: that: http://www.mkyong.com/java/how-to-change-the-file-last-modified-date-in-java/
When download list of files, like all files returned by by FTPClient.mlistDir or FTPClient.listFiles, use the timestamp returned with the listing to update timestemp of local downloaded files:
String remotePath = "/remote/path";
String localPath = "C:\\local\\path";
FTPFile[] remoteFiles = ftpClient.mlistDir(remotePath);
for (FTPFile remoteFile : remoteFiles) {
File localFile = new File(localPath + "\\" + remoteFile.getName());
OutputStream outputStream = new BufferedOutputStream(new FileOutputStream(localFile));
if (ftpClient.retrieveFile(remotePath + "/" + remoteFile.getName(), outputStream))
{
System.out.println("File " + remoteFile.getName() + " downloaded successfully.");
}
outputStream.close();
localFile.setLastModified(remoteFile.getTimestamp().getTimeInMillis());
}
When downloading a single specific file only, use FTPClient.mdtmFile to retrieve the remote file timestamp and update timestamp of the downloaded local file accordingly:
File localFile = new File("C:\\local\\path\\file.zip");
FTPFile remoteFile = ftpClient.mdtmFile("/remote/path/file.zip");
if (remoteFile != null)
{
OutputStream outputStream = new BufferedOutputStream(new FileOutputStream(localFile));
if (ftpClient.retrieveFile(remoteFile.getName(), outputStream))
{
System.out.println("File downloaded successfully.");
}
outputStream.close();
localFile.setLastModified(remoteFile.getTimestamp().getTimeInMillis());
}