I want to offer an interface, response ResponseMessage with responseCode(String) and data(byte[] or BufferedImage) which I would request with xhr(type:Blob) and get the response.
If its responseCode is success, I would show the image saved in data.
I have tried response byte[] and BufferedImage Data, using FileReader and img src to show. But it's of no use and its Content-Type is always "application/json". If I set the response type to "image/jpeg", there will be no Blob. Otherwise I can get the right Blob but I can't translate the Blob to image. What should I do?
This is my ResponseMessage Class:
public class ResponseMessage<T> {
public String responseCode;
public T data;
public String getResponseCode() {
return responseCode;
}
public void setResponseCode(String responseCode) {
this.responseCode = responseCode;
}
public T getData() {
return data;
}
public void setData(T data) {
this.data = data;
}
}
This is response BufferedImage data:
if(maxRect.area()>0) {
Mat roi_img = new Mat(image, maxRect);
Mat tmp_img = new Mat();
roi_img.copyTo(tmp_img);
Imgproc.resize(tmp_img,tmp_img,new Size(50,50));
responseMessage.setResponseCode("00");
responseMessage.setData(Mat2BufferedImage(tmp_img));
return responseMessage;
}
static BufferedImage Mat2BufferedImage(Mat matrix)throws Exception {
MatOfByte mob=new MatOfByte();
Imgcodecs.imencode(".jpg", matrix, mob);
byte ba[]=mob.toArray();
BufferedImage bi=ImageIO.read(new ByteArrayInputStream(ba));
return bi;
}
This is response byte[] data:
if(maxRect.area()>0) {
Mat roi_img = new Mat(image, maxRect);
Mat tmp_img = new Mat();
roi_img.copyTo(tmp_img);
Imgproc.resize(tmp_img,tmp_img,new Size(50,50));
responseMessage.setResponseCode("00");
byte[] return_buff = new byte[(int) (tmp_img.total() *
tmp_img.channels())];
tmp_img.get(0, 0, return_buff);
responseMessage.setData(return_buff);
return responseMessage;
}
Related
I am capturing a live image using JavaScript and storing that image in the database in encrypted form. Below is the code for storing image in database.
Session["imageName"] = DateTime.Now.ToString("dd-MM-yy hh-mm-ss");
Session["imagePath"] = string.Format("{0}.png", Session["imageName"].ToString());
Session["CapturedImage"] = ResolveUrl(Session["imagePath"].ToString());
private static byte[] ConvertHexToBytes(string hex)
{
byte[] bytes = new byte[hex.Length * sizeof(char)];
System.Buffer.BlockCopy(hex.ToCharArray(), 0, bytes, 0, bytes.Length);
return bytes;
}
public static bool SaveCapturedImage(string data)
{
string url = HttpContext.Current.Session["CapturedImage"].ToString();
HttpContext.Current.Session["CapturedImage"] = null;
return true;
}
protected void btnUpload_Click1 (object sender, EventArgs e)
{
using (StreamReader reader = new StreamReader(Request.InputStream))
{
Session["hexString"] = Server.UrlEncode(reader.ReadToEnd());
string filename = Session["imageName"].ToString();
string contentType = Session["imagePath"].ToString();
using (FileStream fs = new FileStream(filename, FileMode.OpenOrCreate, FileAccess.Write))
{
byte[] bytes = ConvertHexToBytes(Session["hexString"].ToString());
string constr = ConfigurationManager.ConnectionStrings["Con2"].ConnectionString;
using (SqlConnection con = new SqlConnection(constr))
{
string query = "insert into tblFiles values (#UId,#Name, #RelativeName, #ImageName, #ContentType, #Data, #uname)";
using (SqlCommand cmd = new SqlCommand(query))
{
cmd.Connection = con;
cmd.Parameters.AddWithValue("#UId", txtId.Text);
cmd.Parameters.AddWithValue("#Name", txtName.Text);
cmd.Parameters.AddWithValue("#RelativeName", txtRName.Text);
cmd.Parameters.AddWithValue("#ImageName", filename);
cmd.Parameters.AddWithValue("#ContentType", contentType);
cmd.Parameters.AddWithValue("#Data", bytes);
cmd.Parameters.AddWithValue("#uname", Session["uname"].ToString());
con.Open();
cmd.ExecuteNonQuery();
con.Close();
this.clear();
}
}
}
}
}
How can I decrypted the image on page load at next page. I have tried many things but am not able to do it.
Thanks.
My web app currently allows users to upload media one-at-a-time using the following:
var fd = new FormData(document.forms[0]);
fd.append("media", blob); // blob is the image/video
$.ajax({
type: "POST",
url: '/api/media',
data: fd
})
The media then gets posted to a WebApi controller:
[HttpPost, Route("api/media")]
public async Task<IHttpActionResult> UploadFile()
{
if (!Request.Content.IsMimeMultipartContent("form-data"))
{
throw new HttpResponseException(HttpStatusCode.UnsupportedMediaType);
}
string mediaPath = await _mediaService.UploadFile(User.Identity.Name, Request.Content);
return Ok(mediaPath);
}
Which then does something along the lines of:
public async Task<string> UploadFile(string username, HttpContent content)
{
var storageAccount = new CloudStorageAccount(new StorageCredentials(accountName, accountKey), true);
CloudBlobClient blobClient = storageAccount.CreateCloudBlobClient();
CloudBlobContainer imagesContainer = blobClient.GetContainerReference("container-" + user.UserId);
var provider = new AzureStorageMultipartFormDataStreamProvider(imagesContainer);
await content.ReadAsMultipartAsync(provider);
var filename = provider.FileData.FirstOrDefault()?.LocalFileName;
// etc
}
This is working great for individual uploads, but how do I go about modifying this to support batched uploads of multiple files through a single streaming operation that returns an array of uploaded filenames? Documentation/examples on this seem sparse.
public class AzureStorageMultipartFormDataStreamProvider : MultipartFormDataStreamProvider
{
private readonly CloudBlobContainer _blobContainer;
private readonly string[] _supportedMimeTypes = { "images/png", "images/jpeg", "images/jpg", "image/png", "image/jpeg", "image/jpg", "video/webm" };
public AzureStorageMultipartFormDataStreamProvider(CloudBlobContainer blobContainer) : base("azure")
{
_blobContainer = blobContainer;
}
public override Stream GetStream(HttpContent parent, HttpContentHeaders headers)
{
if (parent == null) throw new ArgumentNullException(nameof(parent));
if (headers == null) throw new ArgumentNullException(nameof(headers));
if (!_supportedMimeTypes.Contains(headers.ContentType.ToString().ToLower()))
{
throw new NotSupportedException("Only jpeg and png are supported");
}
// Generate a new filename for every new blob
var fileName = Guid.NewGuid().ToString();
CloudBlockBlob blob = _blobContainer.GetBlockBlobReference(fileName);
if (headers.ContentType != null)
{
// Set appropriate content type for your uploaded file
blob.Properties.ContentType = headers.ContentType.MediaType;
}
this.FileData.Add(new MultipartFileData(headers, blob.Name));
return blob.OpenWrite();
}
}
Assuming your AzureStorageMultipartFormDataStreamProvider is similar to the same class mentioned on this blog, that is actually already processing multiple files if there are multiple files in the request.
So all you need to do is change your UploadFile to return a IEnumerable<string> and change your controller to have mediaPath as such.
So your MediaService would have:
var filenames = provider.FileData.Select(x => x.LocalFileName).ToList(); ;
return filenames;
And your controller would have:
var mediaPaths = await _mediaService.UploadFile(User.Identity.Name, Request.Content);
return Ok(mediaPaths);
Since you don't post the related codes with the AzureStorageMultipartFormDataStreamProvider class.
So I create a custom AzureStorageMultipartFormDataStreamProvider which inherits from the MultipartFileStreamProvider to enable the web api upload batched uploads of multiple files.
In the AzureStorageMultipartFormDataStreamProvider we could override the ExecutePostProcessingAsync method.
In this method, we could get the upload file data, then we could upload these data to the azure storage.
More details, you could refer to below codes. The total Controller.
public class UploadingController : ApiController
{
public Task<List<FileItem>> PostFile()
{
if (!Request.Content.IsMimeMultipartContent("form-data"))
{
throw new HttpResponseException(HttpStatusCode.UnsupportedMediaType);
}
var multipartStreamProvider = new AzureStorageMultipartFormDataStreamProvider(GetWebApiContainer());
return Request.Content.ReadAsMultipartAsync<AzureStorageMultipartFormDataStreamProvider>(multipartStreamProvider).ContinueWith<List<FileItem>>(t =>
{
if (t.IsFaulted)
{
throw t.Exception;
}
AzureStorageMultipartFormDataStreamProvider provider = t.Result;
return provider.Files;
});
}
public static CloudBlobContainer GetWebApiContainer(string containerName = "webapi-file-container")
{
// Retrieve storage account from connection-string
CloudStorageAccount storageAccount = CloudStorageAccount.Parse(
"your connection string");
// Create the blob client
CloudBlobClient blobClient = storageAccount.CreateCloudBlobClient();
CloudBlobContainer container = blobClient.GetContainerReference(containerName);
// Create the container if it doesn't already exist
container.CreateIfNotExists();
// Enable public access to blob
var permissions = container.GetPermissions();
if (permissions.PublicAccess == BlobContainerPublicAccessType.Off)
{
permissions.PublicAccess = BlobContainerPublicAccessType.Blob;
container.SetPermissions(permissions);
}
return container;
}
}
public class FileItem
{
/// <summary>
/// file name
/// </summary>
public string Name { get; set; }
/// <summary>
/// size in bytes
/// </summary>
public string SizeInMB { get; set; }
public string ContentType { get; set; }
public string Path { get; set; }
public string BlobUploadCostInSeconds { get; set; }
}
public class AzureStorageMultipartFormDataStreamProvider : MultipartFileStreamProvider
{
private CloudBlobContainer _container;
public AzureStorageMultipartFormDataStreamProvider(CloudBlobContainer container)
: base(Path.GetTempPath())
{
_container = container;
Files = new List<FileItem>();
}
public List<FileItem> Files { get; set; }
public override Task ExecutePostProcessingAsync()
{
// Upload the files to azure blob storage and remove them from local disk
foreach (var fileData in this.FileData)
{
var sp = new Stopwatch();
sp.Start();
string fileName = Path.GetFileName(fileData.Headers.ContentDisposition.FileName.Trim('"'));
CloudBlockBlob blob = _container.GetBlockBlobReference(fileName);
blob.Properties.ContentType = fileData.Headers.ContentType.MediaType;
//set the number of blocks that may be simultaneously uploaded
var requestOption = new BlobRequestOptions()
{
ParallelOperationThreadCount = 5,
SingleBlobUploadThresholdInBytes = 10 * 1024 * 1024 ////maximum for 64MB,32MB by default
};
//upload a file to blob
blob.UploadFromFile(fileData.LocalFileName, options: requestOption);
blob.FetchAttributes();
File.Delete(fileData.LocalFileName);
sp.Stop();
Files.Add(new FileItem
{
ContentType = blob.Properties.ContentType,
Name = blob.Name,
SizeInMB = string.Format("{0:f2}MB", blob.Properties.Length / (1024.0 * 1024.0)),
Path = blob.Uri.AbsoluteUri,
BlobUploadCostInSeconds = string.Format("{0:f2}s", sp.ElapsedMilliseconds / 1000.0)
});
}
return base.ExecutePostProcessingAsync();
}
}
The result like this:
I would checkout uploading the media directly to the blob storage after getting the SAS token for all your files from the Web API in one request. Upload the files using a promise and http get from your client, which will parallelize the upload.
Which will be your right design and approach. Which will also increase your upload speed and reduce the latency.
I try to upload a file from an angularJS front to a jboss backoffice, but i get this exeption when service is called:
Caused by: com.fasterxml.jackson.databind.JsonMappingException: Can not deserialize instance of byte[] out of START_OBJECT token
at [Source: io.undertow.servlet.spec.ServletInputStreamImpl#1cc8ac9f; line: 1, column: 39] (through reference chain: fr.test.Document["datas"
])
I guess there is something wrong when i convert the javascript File in java bytes[], but i don't really know what.
I collect the file via a regular input type="file":
<input
type="file"
style="display: none;"
onchange="angular.element(this).controller().addDocument(this)"
>
Then i catch result with an onchange method in my controller:
(i read on this link Return the Array of Bytes from FileReader() that i have to use a promise, that's return a bytes array).
...
ctrl.addDocument = function(element){
var file = element.files[0];
var fileData = new Blob([element.files[0]]);
var promise = new Promise(
function(resolve){
var reader = new FileReader();
reader.readAsArrayBuffer(fileData);
reader.onload = function() {
var arrayBuffer = reader.result
var bytes = new Uint8Array(arrayBuffer);
resolve(bytes);
}
}
);
promise.then(function(data) {
var document = {
name: file.name,
type: file.type,
datas: data
};
console.dir(document);
ctrl.doc = document;
}).catch(function(err) {
console.log(err);
growl.error('Unable to upload file');
});
}
...
Finally, backoffice is called, using a rest service. Here the declaration of my backoffice's service:
#POST
#Path("/uploadFile")
#Consumes(MediaType.APPLICATION_JSON)
public void uploadFile(Document document) {
LOGGER.info("upload document !");
}
And the document object that contains same properties:
public class Document {
private byte[] datas;
private String name;
private String type;
public byte[] getDatas() {
return datas;
}
public void setDatas(byte[] datas) {
this.datas = datas;
}
...
If i comment the line "ctrl.doc = document;" in my controller (the bytes part), service work correctly.
What i missed ? Can i really send a file this way ?
I have a problem with my created zip file. I am using Java 8. I tried to create a zip file out of a byte array, which contains two or more Excel files. . So, I thought everything is alright. I do an ajax call for create and download my file but i don't have the popup for download my zip and i don't have error.
This is my javascript:
function getFile() {
$.ajax({
type: "POST",
url: "/support-web/downloadCSV",
dataType: "json",
contentType: 'application/json;charset=UTF-8',
data: jsonfile,
success: function (data) {
console.log("in sucess");
window.location.href="/support-web/downloadCSV/"+data
},
error:function (xhr, ajaxOptions, thrownError){
console.log("in error")
}
});
}
This is my Controller:
#Controller
#RequestMapping(value = "/downloadCSV")
public class DownloadCSVController {
private static final int BUFFER_SIZE = 4096;
#RequestMapping(method = RequestMethod.POST)
#ResponseBody
public void downloadCSV(HttpServletRequest request, HttpServletResponse response, #RequestBody String json)
throws IOException {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
try (ZipOutputStream zos = new ZipOutputStream(baos)) {
int i = 0;
for (String url : parts) {
i++;
URL uri = new URL(url);
HttpURLConnection httpConn = (HttpURLConnection) uri.openConnection();
int responseCode = httpConn.getResponseCode();
if (responseCode == HttpURLConnection.HTTP_OK) {
String fileName = "";
String disposition = httpConn.getHeaderField("Content-Disposition");
String contentType = httpConn.getContentType();
int contentLength = httpConn.getContentLength();
if (disposition != null) {
// extracts file name from header field
int index = disposition.indexOf("filename=");
if (index > 0) {
fileName = disposition.substring(index + 9, disposition.length());
}
} else {
// extracts file name from URL
fileName = url.substring(url.lastIndexOf("/") + 1, url.length());
}
System.out.println("Content-Type = " + contentType);
System.out.println("Content-Disposition = " + disposition);
System.out.println("Content-Length = " + contentLength);
System.out.println("fileName = " + fileName);
// opens input stream from the HTTP connection
InputStream inputStream = httpConn.getInputStream();
ZipEntry entry = new ZipEntry(fileName + i + ".csv");
int length = 1;
zos.putNextEntry(entry);
byte[] b = new byte[BUFFER_SIZE];
while ((length = inputStream.read(b)) > 0) {
zos.write(b, 0, length);
}
zos.closeEntry();
inputStream.close();
System.out.println("File downloaded");
}
}
} catch (IOException ioe) {
ioe.printStackTrace();
}
// this is the zip file as byte[]
int size = baos.toByteArray().length;
byte[] reportContent = baos.toByteArray();
// Write file to response.
OutputStream output = response.getOutputStream();
output.write(reportContent);
output.close();
response.setContentType("application/force-download");
response.setContentLength((int)size);
response.setHeader("Content-Transfer-Encoding", "binary");
response.setHeader("Content-Disposition","attachment; filename=\"test.zip\"");//fileName)
System.out.println("FIN TELECHARGEMENT");
}
}
Problem:
The Browser not should open a download box
The response isn't handled in the error or in the success (ajax)
So what do I wrong or what is the proper way to do this?
In my navigator you can see the response with my file but download box not should open
You need to do two things:
Set headers before writing anything to response stream.
Remove output.close(); you should not do that. Stream is opened and closed by container.
Second point actually not affecting your problem, its just an advice. You can read more about it here Should one call .close() on HttpServletResponse.getOutputStream()/.getWriter()?.
I have this code (Java/Android) that takes the bitmap, converts it to byte array, and then puts it into a Map known as 'picture' and is finally sent up via calling the "createcard" function:
public static void createCard(final String nametext, final String initialbalancetext, String databaseclass, String cardnotes, String cardtype, Bitmap picture) {
ByteArrayOutputStream stream = new ByteArrayOutputStream();
picture.compress(Bitmap.CompressFormat.PNG, 100, stream);
byte[] byteArray = stream.toByteArray();
Map<String, Object> map = new HashMap<>();
map.put("cardname", nametext);
map.put("balance", Double.valueOf(initialbalancetext));
map.put("database", databaseclass);
map.put("cardnotes", cardnotes);
map.put("picture", byteArray);
// Check if network is connected before creating the card
if (CardView.isNetworkConnected) {
ParseCloud.callFunctionInBackground("createcard", map, new FunctionCallback<String>() {
#Override
public void done(String s, ParseException e) {
// COMPLETE
CardListCreator.clearadapter();
CardListAdapter.queryList();
}
});
}
This is my "createcard" function (Javascript/Parse Cloudcode). It supposedly takes the 'picture' key and grabs the byte array, and attempts to save it:
Parse.Cloud.define("createcard", function(request, response){
var cardname = request.params.cardname;
var balance = request.params.balance;
var database = request.params.database;
var cardnotes = request.params.cardnotes;
var picture = request.params.picture;
var picturename = "photo.jpg";
var parseFile = new Parse.File(picturename, picture);
parseFile.save().then(function(parseFile){
var currentuser = Parse.User.current();
var CurrentDatabase = Parse.Object.extend(database);
var newObject = new CurrentDatabase;
newObject.set("cardname", cardname);
newObject.set("balance", balance);
newObject.set("user", currentuser);
newObject.set("cardnotes", cardnotes);
newObject.set("cardpicture", parseFile);
newObject.save(null, {
success: function(newObject){
console.log(newObject);
response.success(newObject + " successfully created");
}, error: function(newObject, error){
console.log(error);
response.error(error+" error");
}
})
});
});
Now my problem is that the function is simply not working. I don't know why as my console.log isn't actually logging anything. Does anyone have any ideas?
I hope this code is given your question.
private void Update(){
ParseQuery<ParseObject> query = ParseQuery.getQuery("Table Name");
query.getInBackground(parsekey, new GetCallback<ParseObject>() {
public void done(ParseObject gameScore, ParseException e) {
if (e == null) {
if(camera!=null) {
ByteArrayOutputStream stream = new ByteArrayOutputStream();
camera.compress(Bitmap.CompressFormat.JPEG, 100, stream);
byte imageInByte[] = stream.toByteArray();
encodedImage = Base64.encodeToString(imageInByte, Base64.DEFAULT);
image = new ParseFile("image.txt", imageInByte);
}else{
Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.user_icon);
ByteArrayOutputStream stream = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.JPEG, 100, stream);
byte imageInByte[] = stream.toByteArray();
encodedImage = Base64.encodeToString(imageInByte, Base64.DEFAULT);
image = new ParseFile("image.txt", imageInByte);
}
findViewById(R.id.editName)).getText().toString(),Profile.this);
gameScore.put("name", ((EditText) findViewById(R.id.editName)).getText().toString().trim());
gameScore.put("gender",gender_val);
gameScore.put("country",country_val);
gameScore.put("dateofbirth",((TextView) findViewById(R.id.editdate)).getText().toString().trim());
gameScore.put("profession",profession);
gameScore.put("image",image);
gameScore.saveInBackground();
Toast.makeText(Profile.this,"SuccessFull Updated",Toast.LENGTH_LONG).show();
}else{
Log.e("erroreeeee", DataBase.getUserObjectId(Profile.this)+" "+e.getMessage());
}
}
});
}
For all in the future: You want to put the image into the byte[] and put it into the map. You don't need to encode it to a string, unless you want to decode it in the cloudcode. On the cloudcode, request the param of the byte[] that you uploaded, and then put it into the ParseFile and then finally call save on it.