I have images on machine of server. I want to retrieve image and display it in UI using angularjs.
I convert image to byte array in RestController. In angularjs, I send a request to get byte array then display byte array as an image in html. But image do not show on web page. Below is my code:
#RequestMapping(value = "/images", method = RequestMethod.GET)
public ResponseEntity<byte[]> getProductImage(String fileName) {
byte[] result = null;
File serverFile;
try {
serverFile = productService.getProductImage(fileName);
BufferedImage bufferedImage = ImageIO.read(serverFile);
// get DataBufferBytes from Raster
WritableRaster raster = bufferedImage.getRaster();
DataBufferByte data = (DataBufferByte) raster.getDataBuffer();
result = (data.getData());
} catch (IOException e) {
e.printStackTrace();
}
String mimeType = URLConnection.guessContentTypeFromName(fileName);
HttpHeaders headers = null;
if (mimeType != null) {
headers = new HttpHeaders();
headers.setContentType(MediaType.valueOf(mimeType));
}
return new ResponseEntity<>(Base64.getEncoder().encode(result), headers, HttpStatus.OK);
}
angularjs
vm.getByte = function(fileName){
$http({
method: 'GET',
url: '/api/images',
params: {
fileName: fileName
}
}).success(function(success){
vm.imgFile = success;
});
};
html code
<div class="form-group">
<label>Image</label>
<div class="form-group has-avatar" ng-if="vm.Product.productImg">
<img ng-src="data:image/JPEG;base64,{{vm.imgFile}}" style="width: 200px;height: 130px;" />
current result:
result
You should fix code in java follow:
#RequestMapping(value = "/images", method = RequestMethod.GET)
public ResponseEntity<byte[]> getProductImage(String fileName) {
byte[] result = null;
File serverFile;
try {
serverFile = productService.getProductImage(fileName);
FileInputStream fi = new FileInputStream(serverFile);
result = Base64.getEncoder().encode(IOUtils.toByteArray(fi));
} catch (IOException e) {
e.printStackTrace();
}
String mimeType = URLConnection.guessContentTypeFromName(fileName);
HttpHeaders headers = null;
if (mimeType != null) {
headers = new HttpHeaders();
headers.setContentType(MediaType.valueOf(mimeType));
}
return new ResponseEntity<>(result, headers, HttpStatus.OK);
}
Related
really don't now what to do.
i have on my server xls file and i wont to download it from my client.
i actually do it but the file getting in some weird langue and absolutely broken.
client : angular
server: spring 4
Code
Client
function getXCEL() {
self.onXCELProcess = true;
AdminService.getXL(MotherService.getAppMember())
.then(
function (response) {
var file = new Blob([response], {type: 'application/excel'});
var isChrome = !!window.chrome && !!window.chrome.webstore;
var isIE = /*#cc_on!#*/false || !!document.documentMode;
var isEdge = !isIE && !!window.StyleMedia;
if (isChrome){
var url = window.URL || window.webkitURL;
var downloadLink = angular.element('<a></a>');
downloadLink.attr('href',url.createObjectURL(file));
downloadLink.attr('target','_self');
downloadLink.attr('download', 'yourReports.xls');
downloadLink[0].click();
}
else if(isEdge || isIE){
window.navigator.msSaveOrOpenBlob(file,'yourReports.xls');
}
else {
var fileURL = URL.createObjectURL(file);
window.open(fileURL);
}
self.onXCELProcess = false;
},
function (error) {
console.error("error : "+error+" , error : "+JSON.stringify(error));
self.onXCELProcess = false;
}
)
}
function getXL(admin) {
return MotherService.callToServer({method: 'POST', url: URL + "orderxl", appMember: admin});
}
callToServer() method do request, with json body. and return the deferred.promise
for use of then.
server
#RequestMapping(value = "/"+Request.ADMIN_PATH+"/"+Request.ORDER_XL, method = RequestMethod.POST)
public void getFile(#RequestBody OrderXLRequest request, HttpServletResponse response) {
try {
File file = orderXLService.execute(request).getFile(); //get the file. already saved and ready to send
try{
InputStream inputStream = new FileInputStream(file);
String headerKey = "Content-Disposition";
String headerValue = String.format("attachment; filename=\"%s\"", "excelfilename.xlsx");
response.setHeader(headerKey, headerValue);
try {
FileCopyUtils.copy(inputStream, response.getOutputStream());
} catch (IOException e) {
e.printStackTrace();
}
}catch(Exception e){
System.out.println("Exception in file download :"+e);
}
}catch (Exception e) {
e.printStackTrace();
}
}
thank you very much for any help or suggestion
I have created simple rest method to upload and add file via multipart in Spring Boot.
I don't have any #RequestBody so I'm quite astonished why the browser throws 415 -> "Unsupported Media Type" Content type 'null' not supported
The controller looks like:
#RestController
#RequestMapping(value = "/api/file")
public class FileController {
#Autowired
private FileServiceImpl fileService;
#Autowired
private UserRepository userRepository;
#PreAuthorize("hasAnyAuthority('CLIENT')")
#RequestMapping(value = "", method = RequestMethod.POST, headers = "content-type=multipart/*", produces = "application/json", consumes = MediaType.APPLICATION_JSON_VALUE)
public File uploadFile(#RequestParam("uploadedFile") MultipartFile file, HttpServletRequest httpRequest) {
Principal name = httpRequest.getUserPrincipal();
if (name.getName() == null) {
throw new RuntimeException("Brak sesji");
}
User userByLogin = userRepository.findUserByLogin(name.getName());
File f = null;
if (!file.isEmpty()) {
try {
f = new File(file.getOriginalFilename(), file.getBytes(), file.getName(), file.getContentType(), new Date(), userByLogin);
} catch (IOException e) {
e.printStackTrace();
}
}
if (f != null) {
fileService.uploadFile(f);
}
return f;
}
}
At the frontend looks like
<div>
<label>Dodaj załącznik</label>
<input type="file" files-model="file" >
<button ng-click="addFile()">Dodaj</button>
</div>
$scope.addFile = function () {
FileService.save($scope.file);
}
The fail looks like:
{"timestamp":1491988354597,"status":415,"error":"Unsupported Media Type","exception":"org.springframework.web.HttpMediaTypeNotSupportedException","message":"Content type 'null' not supported","path":"/api/file"}
you have to append your file in formData.
<div>
<label></label>
<input type="file" files-model="file" id="file" >
<button ng-click="addFile()">Dodaj</button>
</div>
$scope.addFile = function () {
var file = document.getElementById("file").files[0];
var formData = new FormData();
formData.append("file", file);
FileService.save(formData);
};
In FileService service you have to set headers: {Content-Type:undefined}
this should work!
I wanna achieve a simple task, which is to retrieve the binary image, and display it in my html
public class Artwork
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public Guid artworkID { get; set; }
public string artworkName { get; set; }
public string artworkMimeType { get; set; }
public byte[] artworkMeta { get; set; }
public string artworkBase64String { get; set; }
}
Gets the artwork from DB
public Artwork GetArtwork(Guid id)
{
return _context.Artworks.SingleOrDefault(a => a.artworkID == id);
}
The API Controller
public IHttpActionResult Get(Guid id)
{
if (id == null)
{
return BadRequest();
}
var artwork = _repository.GetArtwork(id);
if (artwork == null)
return NotFound();
else
return Ok(artwork);
}
I've also used this method and it returns the data I want, but I still don't know how to use it to achieve my goal.
[HttpGet]
public HttpResponseMessage Get(Guid id)
{
HttpResponseMessage result = null;
try
{
var artwork = _repository.GetArtwork(id);
if (artwork == null)
{
result = Request.CreateResponse(HttpStatusCode.Gone);
}
else
{
// sendo file to client
byte[] bytes = artwork.artworkMeta ;
result = Request.CreateResponse(HttpStatusCode.OK);
result.Content = new ByteArrayContent(bytes);
result.Content.Headers.ContentDisposition = new System.Net.Http.Headers.ContentDispositionHeaderValue("attachment");
result.Content.Headers.ContentDisposition.FileName = artwork.artworkName;
}
return result;
}
catch (Exception ex)
{
return Request.CreateResponse(HttpStatusCode.Gone);
}
}
And here's my angular request
$scope.getCity = function (id) {
$http.get('/api/artwork/' + $RouteParams.id).success(function (response) {
$scope.artwork= response;
//I've seen dudes using Blob here, but I'm not sure how that works
});
}
My problem is my angular request and my html, how do I display the artwork without doing this:
<img ng-src="data:{{artwork.artworkartworkMimeType}};base64,{{artwork.artworkBase64String}}" class="img-responsive" />
This displays the image, but I don't like how clumsy it looks, and I'm gonna be working with audio files as well, so I need a clean and understandable way. Please help!
As you said, this can be done by using a blob.
First step is to set the content type to application/octet-stream in the api method
[HttpGet]
public HttpResponseMessage Get(Guid id)
{
HttpResponseMessage result = null;
try
{
var artwork = _repository.GetArtwork(id);
if (artwork == null)
{
result = Request.CreateResponse(HttpStatusCode.Gone);
}
else
{
// sendo file to client
byte[] bytes = artwork.artworkMeta ;
result = Request.CreateResponse(HttpStatusCode.OK);
result.Content = new ByteArrayContent(bytes);
result.Content.Headers.ContentDisposition = new System.Net.Http.Headers.ContentDispositionHeaderValue("attachment");
result.Content.Headers.ContentDisposition.FileName = artwork.artworkName;
result.Content.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream");
}
return result;
}
catch (Exception ex)
{
return Request.CreateResponse(HttpStatusCode.Gone);
}
}
Then add the client request where you create a blob from the response. An url is then created for the blob which will be the source for the img
$scope.fileURL = '';
$http({
method: 'GET',
url: '/api/artwork/' + $RouteParams.id,
responseType: 'arraybuffer',
headers: {
'Access-Control-Allow-Origin': '*',
}
}).success(function (data, status, headers) {
headers = headers();
var contentType = headers['content-type'];
var blob = new Blob([data], { type: contentType });
//Create a url to the blob
$scope.fileURL = window.URL.createObjectURL(blob);
}).error(function (message) {
console.log(message);
});
Then bind url to the ngSrc
<img ng-src="{{fileURL}}" class="img-responsive" />
You could store image in binary format without encoding it to base64. Then it would be simpler to retrive image from DB.
In your asp controller:
[HttpGet]
public FileResult GetPhoto(int id) {
return File(_repository.GetArtwork(id).artworkMeta, "image/jpg");
}
And in angular view:
<img ng-src="/Home/GetPhoto/2" />
i have an issue with getting the conent-disposition information from an uploaded file. The file upload itself is just working fine. But the Content-Disposition is null thats why i dont know the name and type ofthe uploaded file. I am triggering the post via angularJs's $http service.
#Path("/myrest")
#Service
public class RestService<Repsonse> {
private static final String SERVER_UPLOAD_LOCATION_FOLDER = "C://Users/steven/Desktop/upload/";
/**
* Upload a File
*/
#POST
#Path("/upload")
#Consumes(MediaType.MULTIPART_FORM_DATA)
public Response uploadFile(
#FormDataParam("myForm") InputStream fileInputStream,
#FormDataParam("myForm") FormDataContentDisposition fileDetail
) {
if (fileDetail == null) {
System.out.println("form contentDispositionHeader is null");
// return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(Response.Status.INTERNAL_SERVER_ERROR.toString()).build();
} else {
System.out.println("form: " + fileDetail.toString());
}
Random randomno = new Random();
// String filePath = SERVER_UPLOAD_LOCATION_FOLDER + contentDispositionHeader.getFileName();
// String filePath = SERVER_UPLOAD_LOCATION_FOLDER + "bla.png";
String filePath = SERVER_UPLOAD_LOCATION_FOLDER + "test" + randomno.nextInt(10000) + ".jpg";
// save the file to the server
saveFile(fileInputStream, filePath);
String output = "File saved to server location : " + filePath;
return Response.status(200).entity(output).build();
}
// save uploaded file to a defined location on the server
private void saveFile(InputStream uploadedInputStream,
String serverLocation) {
OutputStream outpuStream = null;
try {
outpuStream = new FileOutputStream(new File(serverLocation));
int read = 0;
byte[] bytes = new byte[1024];
outpuStream = new FileOutputStream(new File(serverLocation));
while ((read = uploadedInputStream.read(bytes)) != -1) {
outpuStream.write(bytes, 0, read);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if(outpuStream != null) {
uploadedInputStream.close();
}
if(outpuStream != null) {
outpuStream.flush();
outpuStream.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
The angularJs part:
js:
var file = $scope.myFile;
that.uploadFileToUrl = function(file, uploadUrl){
var fd = new FormData();
fd.append('file', file);
return $http.post(uploadUrl, fd, {
transformRequest: angular.identity,
headers: {'Content-Type': undefined}
});
};
The html part:
<div ng-controller="fileUploadController">
input type="file" file-model="myFile"/>
<br>
<br>
Name: {{myFile.name}} <br>
Size: {{myFile.size}} <br>
Type: {{myFile.type}} <br>
<br>
<br>
<button ng-click="uploadFile();">Upload</button>
</div>
Uploading files with ajax is in XHR level 2 spec and not really supported by all browsers...
Prefer an approach like $.fileUpload ( https://blueimp.github.io/jQuery-File-Upload/ ) for sending file in an angular/ one-page application.
If you do know what you are going, just add file.name or file.fileName in another field of your FormData object and get it that way server-side.
I've been dying for about 6 hours trying to figure out how to make a regular POST request in WP7 , I tried the answers of similar questions posted here and on many other places, I also tried many different APIs POST request, they all lead to one certain problem,
The remote server returned an error: NotFound.
it seems like everytime there's something missing.
So, if you please someone show us how to properly get a POST request right in this WP7
I use this to post to facebook without any problem:
HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(requestUrl);
request.Method = "POST";
request.BeginGetResponse((e) =>
{
try
{
WebResponse response = request.EndGetResponse(e);
// Do Stuff
}
catch (WebException ex)
{
// Handle
}
catch (Exception ex)
{
// Handle
}
}, null);
I assume you would have tried this already so it may be something to do with the post data (which isn't in the above example as facebook uses the query string). Can you give us any more info?
EDIT: This is an (untested) example for writing post data:
HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(requestUrl);
request.Method = "POST";
request.BeginGetRequestStream((e) =>
{
using (Stream stream = request.EndGetRequestStream(e))
{
// Write data to the request stream
}
request.BeginGetResponse((callback) =>
{
try
{
WebResponse response = request.EndGetResponse(callback);
// Do Stuff
}
catch (WebException ex)
{
// Handle
}
catch (Exception ex)
{
// Handle
}
}, null);
}, null);
I use the following class for making POST requests with WP7:
public class PostMultiPartFormData
{
private Dictionary<string, object> Parameters;
private Encoding ENCODING = Encoding.UTF8;
private string BOUNDARY = "-----------------------------wp7postrequest";
public event EventHandler PostComplete;
public void Post(string postbackURL,
Dictionary<string, object> parameters)
{
Parameters = parameters;
Uri url = null;
url = new Uri(postbackURL);
HttpWebRequest request = WebRequest.Create(url) as HttpWebRequest;
request.Method = "POST";
request.ContentType = "multipart/form-data; boundary=" + BOUNDARY;
request.BeginGetRequestStream(new AsyncCallback(SendStatusUpdate), request);
}
private void SendStatusUpdate(IAsyncResult ar)
{
HttpWebRequest request = (HttpWebRequest)ar.AsyncState;
Stream stream = request.EndGetRequestStream(ar);
byte[] byteArray = GetMultipartFormData(Parameters, BOUNDARY);
stream.Write(byteArray, 0, byteArray.Length);
stream.Close();
stream.Dispose();
request.BeginGetResponse(new AsyncCallback(StatusUpdateCompleted), request);
}
private byte[] GetMultipartFormData(Dictionary<string, object> postParameters, string boundary)
{
Stream formDataStream = new System.IO.MemoryStream();
foreach (var param in postParameters)
{
if (param.Value is byte[])
{
byte[] fileData = param.Value as byte[];
string header = string.Format("--{0}\r\nContent-Disposition: form-data; name=\"{1}\"; filename=\"{2}.jpg\";\r\nContent-Type: application/octet-stream\r\n\r\n", boundary, param.Key, param.Key);
formDataStream.Write(ENCODING.GetBytes(header), 0, header.Length);
formDataStream.Write(fileData, 0, fileData.Length);
}
else
{
string postData = string.Format("--{0}\r\nContent-Disposition: form-data; name=\"{1}\"\r\n\r\n{2}\r\n", boundary, param.Key, param.Value);
byte[] b = ENCODING.GetBytes(postData);
foreach (var item in b)
{
formDataStream.WriteByte(item);
}
}
}
string footer = "\r\n--" + boundary + "--\r\n";
byte[] footerbytes = ENCODING.GetBytes(footer);
formDataStream.Write(footerbytes, 0, footerbytes.Length);
formDataStream.Position = 0;
byte[] formData = new byte[formDataStream.Length];
formDataStream.Read(formData, 0, formData.Length);
formDataStream.Flush();
formDataStream.Close();
return formData;
}
private void StatusUpdateCompleted(IAsyncResult ar)
{
if (PostComplete != null)
{
PostComplete(ar, null);
}
}
}
Example:
PostMultiPartFormData postRequest = new PostMultiPartFormData();
postRequest.PostComplete += new EventHandler( (sender, e) =>
{
IAsyncResult ar = ((IAsyncResult)sender);
using (WebResponse resp = ((HttpWebRequest)ar.AsyncState).EndGetResponse(ar))
{
using (StreamReader sr = new StreamReader(resp.GetResponseStream()))
{
string responseString = sr.ReadToEnd();
this.Dispatcher.BeginInvoke(() =>
{
textBlock.Text = responseString;
});
}
}
});
postRequest.Post("http://localhost:50624/SSLProxy.ashx",
new Dictionary<string, object>() { { "param1", "value1" } });
This should work...
If it doesn't let me know! :-)
For easier access to advanced http features check out these http classes:
http://mytoolkit.codeplex.com/wikipage?title=Http
It encapsulates GET, POST, FILES (using path or Stream objects) and GZIP (not directly supported by WP7) requests.
To add post data just call BeginGetRequestStream method (also, BeginGetResponse move to GetRequestStreamCallback)
request.BeginGetRequestStream(new AsyncCallback(GetRequestStreamCallback), request);
void GetRequestStreamCallback(IAsyncResult asynchronousResult)
{
HttpWebRequest webRequest = (HttpWebRequest)asynchronousResult.AsyncState;
// End the stream request operation
Stream postStream = webRequest.EndGetRequestStream(asynchronousResult);
// Create the post data
string postData = "post data";
byte[] byteArray = Encoding.Unicode.GetBytes(postData);
// Add the post data to the web request
postStream.Write(byteArray, 0, byteArray.Length);
postStream.Close();
// Start the web request
webRequest.BeginGetResponse(new AsyncCallback(GetResponseCallback), webRequest);
}
I recommend you to use the postclient. It is pretty simple. You just need to add reference to dll file into your project, and then write something like:
public void authorize(string login, string password)
{
Dictionary<string, object> parameters = new Dictionary<string, object>();
parameters.Add("command", "login");
parameters.Add("username", login);
parameters.Add("password", password);
PostClient proxy = new PostClient(parameters);
proxy.DownloadStringCompleted += (sender, e) =>
{
if (e.Error == null)
{
MessageBox.Show(e.Result);
}
};
proxy.DownloadStringAsync(new Uri("http://address.com/service", UriKind.Absolute));
}